苏州网站建设搜q479185700,seo排名优化有哪些,北京商场恢复营业,高唐住房建设局网站一#xff0c;前言
上一篇#xff0c;主要介绍了 Vuex 插件的开发#xff0c;主要涉及以下几个点#xff1a;
Vuex 插件的使用介绍#xff1b;Vuex 插件开发和使用分析#xff1b;Vuex 插件机制的分析#xff1b;
本篇#xff0c;继续介绍 Vuex 插件机制的实现…一前言
上一篇主要介绍了 Vuex 插件的开发主要涉及以下几个点
Vuex 插件的使用介绍Vuex 插件开发和使用分析Vuex 插件机制的分析
本篇继续介绍 Vuex 插件机制的实现 二Vuex 插件机制分析
通过官方 Vuex 插件所提供的插件机制创建并实现了一个简易的 Vuex 插件
Vuex 插件的实现主要使用 Vuex 提供的以下方法
Vuex 插件的 plugins 数组提供插件注册功能store.subscribe状态变更时的订阅回调功能store.replaceState状态替换功能
本篇继续以 vuex 持久化插件 vuex-persists 为例逐步实现 Vuex 插件提供的机制核心逻辑
三Vuex 插件机制实现
1Vuex 插件的注册
当 new Vuex.Store 初始化时处理 options.plugins 数组中注册的插件函数高阶函数收集 Vuex 插件中通过 store.subscribe 订阅状态变化事件的回调函数 fn 保存到 _subscribes 数组中;
// src/vuex/store.jsexport class Store {constructor(options) {const state options.state;this._actions {};this._mutations {};this._wrappedGetters {};// 收集通过 store.subcribe 订阅状态变更事件的处理函数 fn// 当 mutation 执行时触发全部订阅事件执行返回当前 mutation 和更新后的状态this._subscribes [];this._modules new ModuleCollection(options);installModule(this, state, [], this._modules.root);resetStoreVM(this, state);// 依次执行 options 选项中的 plugins 插件,传入当前 store 实例options.plugins.forEach(plugin plugin(this));}// 提供 store.subscribe 状态变更事件订阅功能// 将回调函数统计收集到 _subscribes 数组中subscribe(fn) {console.log(订阅 Vuex 状态变化收集处理函数)this._subscribes.push(fn);console.log(this._subscribes, this._subscribes)}
}2subscribe 状态订阅实现
当状态变化时即 mutation 方法执行时依次执行 _subscribes 中保存的处理函数 fn传入当前 mutation 和当前根状态 rootState
// src/vuex/store.jsconst installModule (store, rootState, path, module) {// ...module.forEachMutation((mutation, key) {store._mutations[namespace key] (store._mutations[namespace key] || []);store._mutations[namespace key].push((payload) {mutation.call(store, module.state, payload);// 当 mutation 执行时依次执行 store.subscribe 状态变更事件订阅的处理函数 fnstore._subscribes.forEach(fn {console.log(状态更新依次执行订阅处理)fn(mutation, rootState);})})})// ...module.forEachChild((child, key) {installModule(store, rootState, path.concat(key), child);})
}export class Store {constructor(options) {const state options.state;this._actions {};this._mutations {};this._wrappedGetters {};this._subscribes [];this._modules new ModuleCollection(options);// 模块安装处理 mutation 时触发状态变更订阅事件通知installModule(this, state, [], this._modules.root);resetStoreVM(this, state);// 依次执行 options 选项中的 plugins 插件,传入当前 store 实例options.plugins.forEach(plugin plugin(this));}
}测试 Vuex 插件的初始化和状态变化时间订阅
// src/store/index.jsimport Vue from vue;
import Vuex from /vuex; // 使用自开发的 Vuex 插件Vue.use(Vuex);function persists() {return function (store) {console.log(----- persists 插件执行 -----)store.subscribe((mutation, state) {console.log(----- 进入Vuex 插件 store.subscribe 处理函数-----)localStorage.setItem(VUEX:STATE, JSON.stringify(state));})}
}const store new Vuex.Store({plugins: [persists()],
});export default store;在 Vuex 插件初始化过程中 plugins 插件被依次执行并收集插件中通过 store.subscribe 进行状态变更订阅的回调函数 fn 点击按钮更新 Vuex 中的状态在对应 mutation 方法执行时依次调用订阅函数通知 Vuex 插件状态发生变化 订阅回调中处理将当前最新的根状态保存至本地存储 3replaceState 状态替换实现
当状态更新时将最新状态保存至本地存储中当页面刷新时读取本地存储并重新设置 Vuex 状态刷新状态持久化
插件初始化时读取本都存储进行 Vuex 状态同步
// src/store/index.jsimport Vue from vue;
import Vuex from /vuex;Vue.use(Vuex);function persists() {return function (store) {console.log(----- persists 插件执行 -----)// 取出本地存储的状态let data localStorage.getItem(VUEX:STATE);if (data) {console.log(----- 存在本地状态同步至 Vuex -----)// 如果存在使用本地状态替换 Vuex 中的状态store.replaceState(JSON.parse(data));}store.subscribe((mutation, state) {console.log(----- 进入Vuex 插件 store.subscribe 处理函数-----)localStorage.setItem(VUEX:STATE, JSON.stringify(state));})}
}
const store new Vuex.Store({plugins: [persists()]
});
export default store;添加 replaceState 实现并更新插件逻辑统一使用最新状态进行处理
// src/vuex/store.js// 通过当前模块路径 path从最新的根状态上获取模块的最新状态
function getState(store, path){return path.reduce((newState,current){return newState[current];}, store.state); // replaceState 后的最新状态
}const installModule (store, rootState, path, module) {let namespace store._modules.getNamespaced(path);、if (path.length 0) {、let parent path.slice(0, -1).reduce((memo, current) {return memo[current]}, rootState)Vue.set(parent, path[path.length - 1], module.state);}module.forEachMutation((mutation, key) {store._mutations[namespace key] (store._mutations[namespace key] || []);store._mutations[namespace key].push((payload) {// 旧执行 mutation传入当前模块的 state 状态// mutation.call(store, module.state, payload);// 新Vuex 持久化需要使用最新的状态而 module.state是老状态// 需要通过当前路径 path获取到当前最新的状态mutation.call(store, getState(store,path), payload);store._subscribes.forEach(fn {// 旧逻辑:使用根状态 rootState// fn(mutation, rootState);// 新逻辑:使用新状态 store.statefn(mutation, store.state);})})})module.forEachAction((action, key) {store._actions[namespace key] (store._actions[namespace key] || []);store._actions[namespace key].push((payload) {action.call(store, store, payload);})})module.forEachGetter((getter, key) {store._wrappedGetters[namespace key] function () {// 旧逻辑执行对应的 getter 方法传入当前模块的 state 状态返回执行结果// return getter(module.state);// 新逻辑使用最新的状态进行处理return getter(getState(store,path));}})module.forEachChild((child, key) {installModule(store, rootState, path.concat(key), child);})
}function resetStoreVM(store, state) {const computed {};store.getters {};forEachValue(store._wrappedGetters, (fn, key) {computed[key] () {return fn();}Object.defineProperty(store.getters, key, {get: () store._vm[key]});})store._vm new Vue({data: {$$state: state},computed});
}export class Store {constructor(options) {const state options.state;this._actions {};this._mutations {};this._wrappedGetters {};this._subscribes [];this._modules new ModuleCollection(options);installModule(this, state, [], this._modules.root);resetStoreVM(this, state);options.plugins.forEach(plugin plugin(this));}// Vuex 状态替换replaceState(state){this._vm._data.$$state state}
}备注虽然通过 replaceState 实现了 Vuex 插件状态的更新但此时 Vuex 中的逻辑处理中依旧使用的是module.state 或 rootState旧状态需要根据模块路径重新获取对应的新状态进行处理否则页面不会更新涉及 mutation、getter、_subscribes回调传参等相关处理逻辑需更新
4插件效果测试 点击按钮更新状态视图与本地存储同步变化页面刷新后状态持久化成功 四结尾
本篇主要介绍了 Vuex 插件机制的实现主要涉及以下几个点
Vuex 插件机制分析Vuex 插件机制核心逻辑实现:plugins 插件注册、subscribe 订阅收集、replaceState 状态替换
下一篇继续介绍 Vuex 辅助函数的实现