手写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 Store

function 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张图片

三、实现插件机制

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;
    });
  }

你可能感兴趣的:(手写vuex4.x源码,前端,json,javascript)