> 文章列表 > 手写vuex4源码(八)插件机制实现

手写vuex4源码(八)插件机制实现

手写vuex4源码(八)插件机制实现

一、插件的使用

Vuex 不仅提供了全局状态管理能力,还进一步提供了插件机制,便于开发者对 Vuex 插件进行增强;

Vuex 插件的使用方式:通过 Store 类提供的 plugin 数组进行 Vuex 插件注册:

export default createStore({plugins:[ //插件会按照注册的顺序依次执行插件,执行的时候会把store传递给你customlugin],
...})

二、vuex持久化插件开发

1、customlugin插件介绍

在使用 Vuex 插件进行状态管理时,一定会遇到一个问题:当页面刷新时(如使用 F5 进行刷新),将导致页面状态丢失
为了防止vuex的数据,开发customlugin插件

2、customlugin插件实现

(1)vuex插件实现

  • 创建一个 Vuex 插件,最终导出一个高阶函数(在 plugin 数组中进行插件注册);
  • store.subscribe:订阅方法,当 mutation 方法触发时会触发这个方法
  • store.replaceState:替换方法,可以不通过mutation更新state的值

(2)customlugin实现原理

  • 创建一个函数:customPlugin,vuex初始化时,对插件进行注册和初始化操作
  • 使用 store.subscribe 订阅方法:当 mutation 方法触发时,将当前状态保存到本地
  • 当页面刷新时,状态将会丢失,同时 Vuex 插件重新初始化,此时重新读取本地状态,并通过store.replaceState将本地状态(即刷新丢失的状态)替换到 Vuex 状态,实现状态的持久化效果;
import { createStore } from '@/vuex' // new Storefunction customPlugin(store) {let local = localStorage.getItem('VUEX:STATE');//如果localstorage中存在VUEX:STATE,则取出给vuex赋值if (local) {store.replaceState(JSON.parse(local))}store.subscribe((mutation, state) => { // 每当状态发生变化 (调用了mutation的时候 就会执行此回调)localStorage.setItem('VUEX:STATE', JSON.stringify(state))})
}const store = createStore({plugins: [ // 会按照注册的顺序依次执行插件,执行的时候会把store传递给你customPlugin],...
})

手写vuex4源码(八)插件机制实现

三、实现插件机制

1、注册plugin

  • 在store中的数据和方法定义完成后,挨个初始化plugin中的方法
  • 收集 Vuex 插件中,通过 store.subscribe 订阅状态变化事件的回调函数 fn 保存到 _subscribes 数组中;
export default class Store {
...constructor(options) {// 定义状态const state = store._modules.root.state; // 根状态installModule(store, state, [], store._modules.root);resetStoreState(store, state);store._subscribes = [];options.plugins.forEach(plugin => plugin(store));}// 将回调统计到_subscribes数组中subscribe(fn) {this._subscribes.push(fn);}
}

2、subscribe 状态订阅实现

当mutations方法执行时,依次执行_subscribes中的方法,将当前的mutation方法和state一起传递过去,执行当时定义的将数据存在localStorage的方法

commit = (type, payload) => {const entry = this._mutations[type] || [];this._withCommit(() => {entry.forEach((handler) => handler(payload));});this._subscribes.forEach((sub) => sub({ type, payload }, this.state));};

3、replaceState 状态替换实现

replaceState 传入的是本地存储中的state,由于在严格模式下不通过mutation给state赋值会报错,所以在这里借助_withCommit方法,mutation中为了防止异步和其余方法该值也是通过这个进行判断的

 replaceState(newState) {// 严格模式下不能直接更改状态this._withCommit(() => {this._state.data = newState;});}