vueX

作者: lmem | 来源:发表于2016-10-28 12:22 被阅读578次

VueX 才坑指南

1.不支持...mapActions([语法

解决方法很简单了,可以安装整个stage2的预置器或者安装 Object Rest Operator
的babel插件 babel-plugin-transform-object-rest-spread
配置文件添加
{ "presets": [ ["es2015"] ], "plugins": ["transform-object-rest-spread"]}

2.getters数据获得不到

export const getUsers = state => {
    //这里非常重要!!!!user表示模块名
    return state.user.users;
}
3.

1.什么是Vuex

是组件之间的状态管理器。

2.为什么??

look下面的图

Paste_Image.png

问题:
组件不能共享数据,如果共享只能通过引用父组件,导致状态有多个。代码失控

Paste_Image.png

3.demo1

// Make sure to call Vue.use(Vuex) first if using a module system

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})
//只能通过提交action来改变状态,因为统一,易读,方便控制
store.commit('increment')
console.log(store.state.count) // -> 1

4.State

解决了我一开始的疑问
Using Vuex doesn't mean you should put all the state in Vuex. Although putting more state into Vuex makes your state mutations more explicit and debuggable, sometimes it could also make the code more verbose and indirect.
整个应用只有一个状态树
问题1:如何把vuex的状态放在vue组件中
用computed

// let's create a Counter component
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

问题二:store的引用问题
Vue.use(Vuex)注入到所有的子组件中

const app = new Vue({
  el: '#app',
  // provide the store using the "store" option.
  // this will inject the store instance to all child components.
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})
//给父组件提供store 
//会自动注入到子 components 
// 直接使用this.$store
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

问题三:可能属性比较多,如上写法比较冗余和麻烦

// in standalone builds helpers are exposed as Vuex.mapState
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // arrow functions can make the code very succinct!
    count: state => state.count,

    // passing the string value 'count' is same as `state => state.count`
    countAlias: 'count',

    // to access local state with `this`, a normal function must be used
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
    computed: mapState([
        // map this.count to store.state.count
        'count'
    ])
  })
}

问题四:如果想合并其他来源的数据,利用ECMAScript语法

computed: {
  localComputed () { /* ... */ },
  // mix this into the outer object with the object spread operator
  ...mapState({
    // ...
  })
}

5.Getters

问题:如下所示,基于计算的属性,如果在多个地方用咋办,每个地方写,冗余

computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

解决,利用getter

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

然后我们可以直接使用

store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]

可以接受两个参数

getters: {
  // ...
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}
store.getters.doneTodosCount // -> 1

通4中的,我们可以用mapGetters来
simply maps store getters to local computed properties:

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
    // mix the getters into computed with object spread operator
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}

6.Mutations

只能用mutation改变状态

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // mutate state
      state.count++
    }
  }
})
//提交
store.commit('increment')

如果想要传参??

// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit('increment', {
  amount: 10
})

另一种方式

store.commit({
  type: 'increment',
  amount: 10
})

增加状态,只能按照vue的方式

Use Vue.set(obj, 'newProp', 123)
或者直接来一个新的
state.obj = { ...state.obj, newProp: 123 }

增加常量方便操作

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // we can use the ES2015 computed property name feature
    // to use a constant as the function name
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})

如何提条Mutation:
this.$store.commit('xxx') 或者 mapMutations

import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      'increment' // map this.increment() to this.$store.commit('increment')
    ]),
    ...mapMutations({
      add: 'increment' // map this.add() to this.$store.commit('increment')
    })
  }
}

7.Actions

actions 提交mutations.
Actions 包含任意异步的操作

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

也可以用ECMAScript

actions: {
  increment ({ commit }) {
    commit('increment')
  }
}

Dispatching Actions
store.dispatch('increment')
一个异步操作的例子

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

// dispatch with a payload
store.dispatch('incrementAsync', {
  amount: 10
})

// dispatch with an object
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

购物车的例子

actions: {
  checkout ({ commit, state }, payload) {
    // save the items currently in the cart
    const savedCartItems = [...state.cart.added]
    // send out checkout request, and optimistically
    // clear the cart
    commit(types.CHECKOUT_REQUEST)
    // the shop API accepts a success callback and a failure callback
    shop.buyProducts(
      products,
      // handle success
      () => commit(types.CHECKOUT_SUCCESS),
      // handle failure
      () => commit(types.CHECKOUT_FAILURE, savedCartItems)
    )
  }
}

Dispatching Actions in Components

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment' // map this.increment() to this.$store.dispatch('increment')
    ]),
    ...mapActions({
      add: 'increment' // map this.add() to this.$store.dispatch('increment')
    })
  }
}

因为action是异步的,如何在异步结束后做处理??

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}
Now you can do:

store.dispatch('actionA').then(() => {
  // ...
})
//可以在其他action中
actions: {
  // ...
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}

8.Modules

However, as our application grows in scale, the store can get really bloated.

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA's state
store.state.b // -> moduleB's state

Module Local State

const moduleA = {
  state: { count: 0 },
  mutations: {
    increment: (state) {
      // state is the local module state
      state.count++
    }
  },

  getters: {
    doubleCount (state) {
      return state.count * 2
    }
  }
}

context.state will expose the local state, and root state will be exposed as context.rootState
:

const moduleA = {
  // ...
  actions: {
    incrementIfOdd ({ state, commit }) {
      if (state.count % 2 === 1) {
        commit('increment')
      }
    }
  }
}

nside module getters, the root state will be exposed as their 3rd argument:

const moduleA = {
  // ...
  getters: {
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

Namespacing

// types.js

// define names of getters, actions and mutations as constants
// and they are prefixed by the module name `todos`
export const DONE_COUNT = 'todos/DONE_COUNT'
export const FETCH_ALL = 'todos/FETCH_ALL'
export const TOGGLE_DONE = 'todos/TOGGLE_DONE'
// modules/todos.js
import * as types from '../types'

// define getters, actions and mutations using prefixed names
const todosModule = {
  state: { todos: [] },

  getters: {
    [types.DONE_COUNT] (state) {
      // ...
    }
  },

  actions: {
    [types.FETCH_ALL] (context, payload) {
      // ...
    }
  },

  mutations: {
    [types.TOGGLE_DONE] (state, payload) {
      // ...
    }
  }
}

相关文章

  • VUEX基本介绍,包含实战示例及代码(基于Vue2.X)

    VUEX 1 VUEX基本介绍 1.1 官方API 1.2 什么是vuex 1.3 Vuex使用场景 1、Vuex...

  • 【文档笔记】-Vuex

    什么是vuex? vuex文档: https://vuex.vuejs.org/zh/[https://vuex....

  • vuex配置

    vuex配置 目录 vuex的五个核心 配置vuex vuex持久化 一、vuex五个核心概念 State 定义状...

  • Vuex

    安装Vuex cnpm install vuex --save-dev Vuex是什么? 这是[Vuex的官网](...

  • Vuex

    1.Vuex概述 2.Vuex基本使用 3.使用Vuex完成todo案例 1.Vuex概述 Vuex是实现组件全局...

  • vuex

    Vuex介绍: Vuex官网:http://vuex.vuejs.org/ Vuex是实现数据状态管理的技...

  • vuex+axios 的开发流程记录

    相关文档 vuex: https://vuex.vuejs.org/zh/ 是否有必要使用vuex vuex是vu...

  • 2019-06-07

    import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)...

  • 配置 vuex 和 vuex 本地持久化

    配置 vuex 和 vuex 本地持久化 目录 vuex是什么 vuex 的五个核心概念State 定义状态(变量...

  • vuex

    配置 vuex 和 vuex 本地持久化 目录 vuex是什么 vuex 的五个核心概念State 定义状态(变量...

网友评论

    本文标题:vueX

    本文链接:https://www.haomeiwen.com/subject/djasuttx.html