We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
import Vue from 'vue' import Vuex from 'vuex' // Vuex 是一个对象,不是构造函数 Vue.use(Vuex) const store = new Vuex.Store({ // 通过Store构造方法构造一个store state: { count: 0 } }) const app = new Vue({ store, // 注入所有的子组件 // ... })
注入后,可以通过Vue实例的$store.state来访问状态值。
Vuex的状态存储是响应式的。当改变状态时,视图也会发生改变。
<div id="app"> {{ this.$store.state.count }} </div> // vm.$store.state.count ++
为了方便,可以利用计算属性在依赖的响应式属性发生改变时而改变的特点,使用计算属性来返回某个状态。
<div id="app"> {{ count }} </div>
const vm = new Vue({ store, // ... computed: { count() { return this.$store.state.count } } })
当一个组件要引入多个状态时,为了方便,可以使用mapState辅助函数。 import { mapState } from 'vuex'
import { mapState } from 'vuex'
mapState函数返回的是一个对象,所以可以使用扩展运算符。
函数可以接收一个数组或一个对象。
computed: { ...mapState(['count']) }
为对象时,键是计算属性名,值可以是字符串或者函数,函数接收$store.state作为参数,函数里this指向实例。
computed: { ...mapState({ // 计算属性名和state子节点名相同,等同于上述传数组的形式 count: state => state.count, // 键值可简写成字符串,等同于`state => state.count` countAlias: 'count', // 为了能够使用 `this` 获取局部状态,必须使用常规函数而不是箭头函数 countPlusLocalState (state) { return state.count + this.localCount } }) }
有时需要在多个组件中对state做一些相同的计算来派生出一个新的状态。这时除了在每个组件中的计算属性中作运算以外,还可以在store当中定义getters(相当于state的计算属性)。尤其是在对一些数组操作时方便。
Getter会暴露为store.getters对象。
<ul> <li v-for="item in $store.getters.doneTodos">item</li> </ul>
const store = new Vuex.Store({ state: { todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] }, getters: { // 接收$store.state作为参数 doneTodos: state => { return state.todos.filter(todo => todo.done) } } })
getter除了可以接收state作为第一个参数,还可以接收getters作为第二个参数来访问其他getter。
getter还可以返回一个函数,实现给getter传参。
getters: { // ... getTodoById: (state) => (id) => { return state.todos.find(todo => todo.id === id) } } // store.getters.getTodoById(2)
同样,可以使用mapGetters辅助函数将store中的getter映射到局部计算属性。
import { mapGetters } from 'vuex' export default { // ... computed: { // 数组 ...mapGetters(['doneTodos']) // 对象 ...mapGetters({ doneTodosAlias: 'doneTodos' }) } }
改变Vuex的store中的状态的唯一方法是提交mutation。(直接通过$store.state.xxx来修改的话在严格模式下会报错)
const store = new Vuex.Store({ strict: true, // 严格模式 state: { count: 1 }, mutations: { increment (state, n) { // 变更状态 state.count += n } } })
需要通过store.commit方法来调用mutation回调。
store.commit('increment', 10)
mutation只接收两个参数,第一个是store.state,第二个是自定义参数。所以当需要传多个参数时,应该传入一个对象。
mapMutations辅助函数将组件中的methods映射为store.commit调用。
store.commit
import { mapMutations } from 'vuex' export default { // ... methods: { // 相当于将`this.increment()`映射为`this.$store.commit('increment')` ...mapMutations(['increment']), ...mapMutations({ // 相当于将`this.add()`映射为`this.$store.commit('increment')` add: 'increment' }) } }
Mutation必须是同步函数,每当提交mutation时状态变更都应在此刻完成,否则难以调试。如果包含异步操作,那么最终状态改变将不知道是谁导致的。
Action可以包含任何异步操作,并最终提交mutation。
这和Mutation的区别是,Action是先执行异步操作,异步完成后提交mutation。这样就能回退到上一步mutation来追踪状态变更。
如果在mutation里执行异步操作,将是先提交mutation,再执行异步操作,最后更新状态。如果有多个mutation同时提交,你将不知道哪个状态变更是哪个mutation导致的,也就不知道回退哪个mutation了。
action同样接收两个参数,第一个是context对象,它与store实例具有相同的方法和属性,但不是store本身。context.commit、context.state、context.getters。第二个是自定义参数。
context.commit
context.state
context.getters
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state, n) { state.count += n } }, actions: { increment (context, n) { setTimeout(() => { context.commit('increment', n) }, 0) } } })
Action通过store.dispatch方法来触发:
store.dispatch('increment', 10)
mapActions辅助函数能将组件的methods映射为store.dispatch调用。
store.dispatch
import { mapActions } from 'vuex' export default { // ... methods: { // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')` ...mapActions([ 'increment']), // 将 `this.add()` 映射为 `this.$store.dispatch('increment')` ...mapActions({ add: 'increment' }) } }
dispatch可处理被触发的action的处理函数返回的Promise,并且仍旧返回Promise
actions: { actionA({ commit }) { return new Promise((resolve, reject) => { setTimeout(() => { commit('someMutation') resolve() }, 1000) }) } }
store.dispatch('actionA').then(() => { // ... })
配合async/await来组合action:
// 假设 getData() 和 getOtherData() 返回的是 Promise actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ dispatch, commit }) { await dispatch('actionA') // 等待 actionA 完成 commit('gotOtherData', await getOtherData()) } }
可以把store分割成模块,每个模块都有自己的state、getters、mutations、actions,并且模块下面还可以再分子模块。
const moduleA = { state: { a: 1 }, getters: { // state和getters为局部的,rootState和rootGetters可访问根模块 aa(state, getters, rootState, rootGetters) { return state.a + '1' } }, mutations: { // state是局部的 changeA(state) { state.a += 'a' } }, actions: { // 局部的ctx,同时可以通过ctx.rootState、ctx.rootGetters访问根的state和getters changeA(ctx) { setTimeout(() => { ctx.commit(changeA) // 局部的mutations // 当要提交根的mutations或者分发根的actions时,可传入第三个参数{root: true} ctx.commit('someMutation', null, {root: true}) ctx.dispatch('someAction', null, {root: true}) }, 0) } } } const moduleB = { state: { ... }, mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { moduleA, moduleB } })
对于模块内的状态,可以这样访问:
store.state.moduleA // -> moduleA 的状态 store.state.moduleB // -> moduleB 的状态
而模块内的getters、mutations、actions会默认注册在全局命名空间下:
store.getters.a store.commit('changeA') store.dispatch('changeA')
如果想要模块具有更高的封装性和复用性,可以给模块添加namespaced: true使其成为带命名空间的模块。
namespaced: true
const moduleA = { namespaced: true, state: { ... }, getters: { ... }, mutations: { ... }, actions: { ... }, // 嵌套模块 modules: { // 如果没有命名空间,则继承父模块的;否则继续下一层路径/ // namespaced: true moduleC: { state: { ... } getters: { ... }, } } }
store.getters['moduleA/bb'] store.commit('moduleA/changeA') store.dispatch('moduleA/changeA') store.getters['moduleA/cc'] // sotre.getters['moduleA/moduleC/cc']
对于辅助函数,在命名空间
computed: { ...mapState({ a: state => state.moduleA.a }) // 或者 ...mapState('moduleA', { a: state => state.a }) }, methods: { ...mapActions(['moduleA/changeA']) // 或者 ...mapActions('moduleA', ['changeA']) }
在store创建之后,可以使用store.registerModule方法注册模块
store.registerModule
// 注册模块 `myModule` store.registerModule('myModule', { // ... }) // 注册嵌套模块 `nested/myModule` store.registerModule(['nested', 'myModule'], { // ... })
可以通过store.unregisterModule(moduleName)卸载动态模块。
store.unregisterModule(moduleName)
The text was updated successfully, but these errors were encountered:
No branches or pull requests
1. 开始
2. state
注入后,可以通过Vue实例的$store.state来访问状态值。
Vuex的状态存储是响应式的。当改变状态时,视图也会发生改变。
为了方便,可以利用计算属性在依赖的响应式属性发生改变时而改变的特点,使用计算属性来返回某个状态。
当一个组件要引入多个状态时,为了方便,可以使用mapState辅助函数。
import { mapState } from 'vuex'
mapState函数返回的是一个对象,所以可以使用扩展运算符。
函数可以接收一个数组或一个对象。
为对象时,键是计算属性名,值可以是字符串或者函数,函数接收$store.state作为参数,函数里this指向实例。
3. getters
有时需要在多个组件中对state做一些相同的计算来派生出一个新的状态。这时除了在每个组件中的计算属性中作运算以外,还可以在store当中定义getters(相当于state的计算属性)。尤其是在对一些数组操作时方便。
Getter会暴露为store.getters对象。
getter除了可以接收state作为第一个参数,还可以接收getters作为第二个参数来访问其他getter。
getter还可以返回一个函数,实现给getter传参。
同样,可以使用mapGetters辅助函数将store中的getter映射到局部计算属性。
4. mutations
改变Vuex的store中的状态的唯一方法是提交mutation。(直接通过$store.state.xxx来修改的话在严格模式下会报错)
需要通过store.commit方法来调用mutation回调。
mutation只接收两个参数,第一个是store.state,第二个是自定义参数。所以当需要传多个参数时,应该传入一个对象。
mapMutations辅助函数将组件中的methods映射为
store.commit
调用。Mutation必须是同步函数,每当提交mutation时状态变更都应在此刻完成,否则难以调试。如果包含异步操作,那么最终状态改变将不知道是谁导致的。
5. actions
Action可以包含任何异步操作,并最终提交mutation。
这和Mutation的区别是,Action是先执行异步操作,异步完成后提交mutation。这样就能回退到上一步mutation来追踪状态变更。
如果在mutation里执行异步操作,将是先提交mutation,再执行异步操作,最后更新状态。如果有多个mutation同时提交,你将不知道哪个状态变更是哪个mutation导致的,也就不知道回退哪个mutation了。
action同样接收两个参数,第一个是context对象,它与store实例具有相同的方法和属性,但不是store本身。
context.commit
、context.state
、context.getters
。第二个是自定义参数。Action通过store.dispatch方法来触发:
mapActions辅助函数能将组件的methods映射为
store.dispatch
调用。dispatch可处理被触发的action的处理函数返回的Promise,并且仍旧返回Promise
配合async/await来组合action:
6. modules
可以把store分割成模块,每个模块都有自己的state、getters、mutations、actions,并且模块下面还可以再分子模块。
对于模块内的状态,可以这样访问:
而模块内的getters、mutations、actions会默认注册在全局命名空间下:
如果想要模块具有更高的封装性和复用性,可以给模块添加
namespaced: true
使其成为带命名空间的模块。对于辅助函数,在命名空间
动态注册模块
在store创建之后,可以使用
store.registerModule
方法注册模块可以通过
store.unregisterModule(moduleName)
卸载动态模块。The text was updated successfully, but these errors were encountered: