一、为什么需要严格模式
为了统一管理数据,我们希望state的修改只能通过mutation
去实现
严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到
<button @click="$store.state.count++">错误修改</button>
二、开启严格模式
开启严格模式,仅需在创建 store 的时候传入 strict: true:
const store = createStore({
// ...
strict: true
})
注意:不要在发布环境下启用严格模式!
严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式,以避免性能损失。
类似于插件,我们可以让构建工具来处理这种情况:
const store = createStore({
// ...
strict: process.env.NODE_ENV !== 'production'
})
三、严格模式实现
首先将_commiting
设置为false,执行commit的方法前,先将值改为true,监听state的变化,添加判断 如果值为true,则证明是在mutation中修改的数据,如果是false则在控制台断言报错
// 调用的时候知道是mutation,得写同步代码
// 在mutation之前添加一个状态,_commiting = true 之后调用mutation,更改状态,如果当前状态变化时commiting是true,说明是同步更改,如果是false说明是异步更改
this._commiting = false;
commit = (type, payload) => {
const entry = this._mutations[type] || [];
this._withCommit(() => {
entry.forEach((handler) => handler(payload));
});
};
_withCommit(fn) {
// 切片
const commiting = this._commiting;
this._commiting = true;
fn();
this._commiting = commiting;
}
if (store.strict) {
enableStrictMode(store);
}
function enableStrictMode(store) {
watch(
() => store._state.data,
() => {
//监控数据变化,数据变了 重新执行
// 判断commting 如果还是true则证明是同步执行的
// console.assert() 断言,如果是false则会报出后面的错误信息
console.assert(store._commiting,'so not mutate vuex store state outside mutation handlers')
},
{ deep: true, //默认监控一层数据
flush: "sync" //默认是异步,改成同步
}
);
}