Vuex插件

在创建 store 的时候,可以为其配置插件,插件的主要功能是提供一种面向切面 (Aspect Oriented Programming, AOP) 的钩子函数。例如,在 Vuex 中,修改 state 的主要操作来自于 mutation,如果需要监测到 mutation 的调用,可以在每个 mutation 前添加自己的监测逻辑,这其实不难,代码如下:但是对于一个大型的项目中有很多 mutation 的调用,我们能否监测到每次 mutation 的调用又不侵入业务逻辑呢?这就需要用到插件提供的钩子函数来实现,如示例代码 6-8-1 所示。

methods: {
    clb() {
        console.log('mutation调用开始')
        this.$store.commit('increment', {
            num: 4
        })
        console.log('mutation调用结束')
    }
}
示例代码 6-8-1 rootState 和 rootGetter 参数的使用
const myPlugin = (store) => {
    // 当 store 初始化后调用
    store.subscribe((mutation, state) => {
        console.log('mutation调用开始结束')
        // 每次 mutation 之后调用
        // mutation 的格式为 { type, payload }
    })
}
const store = Vuex.createStore({
    plugins: [myPlugin],
    state: {
        count: 3
    },
    mutations: {
        increment(state,params) {
            state.count = state.count + params.num
        }
    }
})
const counter = {
    template: '<div>{{ count }}<button @click="clb">增加</button></div>',
    methods:{
        clb(){
            // 通过this.$store.commit调用mutations
            this.$store.commit('increment', {
                num: 4
            })
        }
    }
}

上面的代码中,首先定义了一个插件,在插件中采用 store.subscribe 方法就可以监测到使用该 store 下所有的 mutation 调用。每当我们调用 increment 时就会进入这个方法,其中第一个参数 mutation 是当前调用的 mutation 内容,type 是 increment 的名字,payload 是 increment 的参数。第二个参数是当前 state 的内容。这样,我们就在不侵入原有业务逻辑代码的情况下实现了 mutation 的监测。

利用插件,我们也可以记录 state 快照,每当 state 改变时都记录下前后的差异,这样更加有利于 Vuex 的调试,这也是 Chrome 浏览器的 Vue DevTools 工具的核心功能之一,代码如下:

const myPluginWithSnapshot = (store) => {
    let prevState = _.cloneDeep(store.state)
    store.subscribe((mutation, state) => {
        let nextState = _.cloneDeep(state)
        // 比较 prevState 和 nextState
        // 保存状态,用于下一次 mutation
        prevState = nextState
    })
}

也可以在插件中打印逻辑日志,相当于记录用户的操作,这些都是 Vuex 插件给我们提供的非常便利的功能。