State
定义State
const store = new Vuex.Store({ state: { todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] } })
State获取
// 实例获取 store.state.count // 组件中获取 this.$store.state.count
mapState辅助函数
import { mapState } from 'vuex' export default { computed: mapState({ // 箭头函数可使代码更简练 count: state => state.count, // 传字符串参数 'count' 等同于 `state => state.count` countAlias: 'count', // 为了能够使用 `this` 获取局部状态,必须使用常规函数 countPlusLocalState (state) { return state.count + this.localCount } }) }
使用扩展运算符
export default { computed: { localComputed () {}, ...mapState({ // 使用扩展运算符进行state混入 }) } }
Getter
定义Getter
const store = new Vuex.Store({ getters: { doneTodos: state => { return state.todos.filter(todo => todo.done) } } })
Getters获取
// 实例中获取 store.getters.count // 组件中获取 this.$store.getters.count
Getters访问
// 属性访问 const store = new Vuex.Store({ getters: { doneTodos: state => state.todos, doneTodosCount: (state, getters) => { return getters.doneTodos.length } } }) // 方法访问 const store = new Vuex.Store({ getters: { getTodoById: (state) => (id) => { return state.todos.find(todo => todo.id === id) } } }) store.getters.getTodoById(2)
mapGetters辅助函数
import { mapGetters } from 'vuex' export default { computed: { // 使用扩展运算符进行getters混入 ...mapGetters([ "doneTodosCount", "anotherGetter" ]) // 对getters取别名 mapGetters({ // 把this.doneCount映射为this.$store.getters.doneTodosCount doneCount:"doneTodosCount" }) } }
Mutation
定义Mutation
const store = new Vuex.Store({ mutations: { increment (state, payload) { // 变更状态 state.count++ } } })
提交Mutation
// payload为载荷 store.commit('increment', payload) // 载荷形式 store.commit('increment', { amount: 10 }) // 对象形式 store.commit({ type: 'increment', amount: 10 })
mapMutations辅助函数
import { mapMutations } from 'vuex' export default { methods: { ...mapMutations([ "increment", // 将this.increment()映射为this.$store.commit('increment') "incrementBy" // 将this.incrementBy(amount)映射为this.$store.commit('incrementBy', amount) ]), ...mapMutations({ add: 'increment' // 将this.add()映射为this.$store.commit('increment') }) } }
注意
mutation应该专注同步事务
应该使用大写常量表示Mutation事件类型
Action
定义Action
const store = new Vuex.Store({ actions: { increment1 (context) { // context为与store类似的对象 context.commit('increment') }, increment2 ({ commit }) { // 可以对context解构赋值 setTimeout(() => { // action层的好处在于,可以进行异步处理 commit('increment') }, 1000) } } })
分发Action
store.dispatch('increment') // 载荷形式 store.dispatch('incrementAsync', { amount: 10 }) // 对象形式 store.dispatch({ type: 'incrementAsync', amount: 10 })
mapActions辅助函数
import { mapActions } from 'vuex' export default { methods: { ...mapActions([ "increment", // 将this.increment()映射为this.$store.dispatch('increment') "incrementBy" // 将this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount) ]), ...mapActions({ add:"increment" // 将this.add()映射为this.$store.dispatch('increment') }) } }
组合Action
store.dispatch接受从action方法中返回的Promise
组合实例one
actions: { actionA ({ commit }) { return new Promise((resolve, reject) => { setTimeout(() => { commit('someMutation') resolve() }, 1000) }) } } store.dispatch('actionA').then(() => { // ... }) // 在另外一个action中也可以 actions: { actionB ({ dispatch, commit }) { return dispatch('actionA').then(() => { commit('someMutation') }) } }
- 组合实例two
actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ dispatch, commit }) { await dispatch('actionA') // 等待actionA完成 commit('gotOtherData', await getOtherData()) } }
Module
基本使用
const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } })
模块的局部状态
模块内部的mutation和getter,接收的第一个参数是模块的局部状态对象
模块内部的action,局部状态通过context.state访问,根节点状态则为context.rootState
命名空间
通过模块内添加namespaced: true属性实现
使用模块内容时,不需要在同一模块内额外添加空间名前缀
命名空间模块——访问全局内容
getter中,rootState和rootGetter会作为第三和第四参数传入
action中,通过context对象的属性传入action
全局分发action或提交mutation,将{ root: true }作为第三参数传给dispatch或commit即可
命名空间模块——注册全局action
{ actions: { someOtherAction ({dispatch}) { dispatch('someAction') } }, modules: { foo: { namespaced: true, actions: { someAction: { root: true, handler (namespacedContext, payload) {} // -> 'someAction' } } } } }
命名空间的绑定函数
// 繁琐用法 computed: { ...mapState({ a: state => state.some.nested.module.a, b: state => state.some.nested.module.b }) }, methods: { ...mapActions([ 'some/nested/module/foo', 'some/nested/module/bar' ]) } // 简洁用法 computed: { ...mapState('some/nested/module', { a: state => state.a, b: state => state.b }) }, methods: { ...mapActions('some/nested/module', [ 'foo', 'bar' ]) } // createNamespacedHelpers用法 import { createNamespacedHelpers } from 'vuex' const { mapState, mapActions } = createNamespacedHelpers('some/nested/module') export default { computed: { // 在 `some/nested/module` 中查找 ...mapState({ a: state => state.a, b: state => state.b }) }, methods: { // 在 `some/nested/module` 中查找 ...mapActions([ 'foo', 'bar' ]) } }
模块动态注册
- 动态注册myModule模块
store.registerModule('myModule', {}) store.registerModule(['nested', 'myModule'], {}) // 注册嵌套模块nested/myModule
可以使用store.unregisterModule('myModule')来动态卸载模块(不能卸载静态模块)
如果想保留过去的state,可以通过 preserveState选项将其归档
store.registerModule('a', module, { preserveState: true })
模块重用
const MyReusableModule = { state () { return { foo: 'bar' } }, // mutation, action 和 getter 等等... }
项目结构
vuex并不限制你的代码结构,但它规定了一些需要遵守的规则
应用层级的状态应该集中到单个store对象中
提交mutation是更改状态的唯一方法,并且这个过程是同步的
异步逻辑都应该封装到action里面
插件
基本用意
vuex的store接受plugins选项,这个选项暴露出每次mutation的钩子
vuex插件就是一个函数,它接收store作为唯一参数
基本使用
const myPlugin = store => { // 当store初始化后调用 store.subscribe((mutation, state) => { // 每次mutation之后调用 // mutation的格式为{ type, payload } }) } const store = new Vuex.Store({ // ... plugins: [myPlugin] })
在插件内提交Mutation
在插件中不允许直接修改状态,类似于组件,只能通过提交mutation来触发变化
通过提交mutation,插件可以用来同步数据源到store
以同步websocket数据源到store为例
export default function createWebSocketPlugin (socket) { return store => { socket.on('data', data => { store.commit('receiveData', data) }) store.subscribe(mutation => { if (mutation.type === 'UPDATE_DATA') { socket.emit('update', mutation.payload) } }) } } const plugin = createWebSocketPlugin(socket) const store = new Vuex.Store({ state, mutations, plugins: [plugin] })
生成State快照
对state状态对象进行深拷贝
生成状态快照的插件应该只在开发阶段使用
使用webpack或Browserify,让构建工具帮我们处理
const store = new Vuex.Store({ plugins: process.env.NODE_ENV !== 'production' ? [myPluginWithSnapshot] : [] })
内置Logger插件
如果正在使用vue-devtools,则不需要此插件
logger插件会生成状态快照,所以仅在开发环境使用
可以直接通过script标签引入,它会提供全局方法createVuexLogger
基本使用
import createLogger from 'vuex/dist/logger' const store = new Vuex.Store({ plugins: [createLogger()] }) const logger = createLogger({ // 自动展开记录的 mutation collapsed: false, filter (mutation, stateBefore, stateAfter) { // 若 mutation 需要被记录,就让它返回true即可 // 顺便,`mutation` 是个{ type, payload }对象 return mutation.type !== "aBlacklistedMutation" }, transformer (state) { // 在开始记录之前转换状态 // 例如,只返回指定的子树 return state.subTree }, mutationTransformer (mutation) { // mutation 按照{ type, payload }格式记录 // 我们可以按任意方式格式化 return mutation.type }, // 自定义console实现,默认为console logger: console })
严格模式
严格模式下,无论何时发生了状态变更且不是由mutation函数引起的,将会抛出错误
严格模式能保证所有的状态变更都能被调试工具跟踪到
示例代码
const store = new Vuex.Store({ // ... strict: true })
表单处理
- 处理方式一
// 组件中 <input :value="message" @input="updateMessage"> { computed: { ...mapState({ message: state => state.obj.message }) }, methods: { updateMessage (e) { this.$store.commit('updateMessage', e.target.value) } } } // store中 mutations: { updateMessage (state, message) { state.obj.message = message }
- 处理方式二
<input v-model="message"> computed: { message: { get () { return this.$store.state.obj.message }, set (value) { this.$store.commit('updateMessage', value) } } }
来源:https://www.cnblogs.com/kanyu/p/12222727.html