用简短的60行代码实现mini-vuex

前言

60 行实现了部分功能,并没有全部实现,但是代码非常简单

功能包括:

  • State
  • Mutations
  • dispatch 【注:vuex中是操作异步,我这里并没有这样写,目的是实现功能】

如图:

mini-vuex 工作原理

  1. 初始化 Store:首先,在 Vue 应用中初始化 Vuex 的 Store。这个 Store 包含了应用的所有状态、操作。
  2. 组件中访问状态 :在 Vue 组件中,通过 this.$store 访问到 Vuex 的 Store 对象。这使得组件能够直接从 Store 中读取状态。
  3. 提交 Mutation 修改状态:当组件需要修改状态时,它会通过提交 Mutation 的方式来请求状态的修改。Mutation 是同步操作,它们包含了状态的修改逻辑。
  4. 状态变更:当一个 Mutation 被提交后,它会修改 Store 中的状态。这个状态的修改是响应式的,所以任何依赖于这个状态的组件都会立即更新。

实现mini-vuex

清楚了工作原理这些我们现在分步来实现 mini-vuex

一、初始化 Store

想要使用 Vue.use() 那就必须得实现一个 install 那么我们来实现这一段,代码如下:

js 复制代码
let Vue

export Class Store {
}

function install(_Vue) {
  Vue = _Vue;
  Vue.mixin({
    beforeCreate: vuexInit,
  });
  function vuexInit() {
    const options = this.$options;
    if (options.store) {
      this.$store =
        typeof options.store === "function" ? options.store() : options.store;
    } else if (options.parent && options.parent.$store) {
      this.$store = options.parent.$store;
    }
  }
}

export default {
  Store,
  install,
};

vuexInit 这个方法的主要目的是在 Vue 组件中初始化 Vuex store。

在 Vue 组件的选项对象中,如果存在 store 属性,那么这个方法会检查 store 属性的类型。如果 store 是一个函数,那么它会调用这个函数并将返回的结果赋值给 this.$store。如果 store 不是一个函数,那么它会直接将 store 的值赋给 this.$store

如果在 Vue 组件的选项对象中没有 store 属性,但是存在 parent 属性,并且 parent 对象有 $store 属性,那么这个方法会将 parent$store 属性的值赋给 this.$store。使得在组件中可以通过 this.$store 访问到 Vuex store。

二、组件中访问状态

简单理解就是 我想通过 this.$store.state.xxx 访问到某个具体属性,上述代码中,我们是并没有对 Store 这个类进行赋值的,那么接下来,我们就实现这个功能

js 复制代码
let Vue;

export class Store {
  constructor({ state = {}, mutations = {} } = {}) {
    // 使用一个 Vue 实例来存储状态树
    this._vm = new Vue({
      data: state,
    });
  }
  
  get state() {
    return this._vm._data;
  }
}

我们在外部存储了一份 Vue ,在我们 install 的时候 Vue = _Vue 完成存储,所以我们在 constructor 中定义了一个存储状态树将 state 保存在Vue上,实现了响应式,通过我们的 get关键字 ,当你访问 this.state 会执行这个 get state() 返回 this._vm._data,即 Vue 实例的数据对象。这样,通过这个 getter 函数,你可以直接访问 Vue 实例的数据对象,而无需直接访问 Vue 实例的 _data 属性

三、提交 Mutation 修改状态 和 状态变更

我们实现 this.$store.dispatch("事件名","值") ,通过他来改变和更新我们的状态

js 复制代码
let Vue;

export class Store {
  constructor({ state = {}, mutations = {} } = {}) {
    // 将 dispatch 绑定到自身
    const dispatch = this.dispatch;
    this.dispatch = (...args) => {
      dispatch.apply(this, args);
    };
    // 使用一个 Vue 实例来存储状态树
    this._vm = new Vue({
      data: state,
    });

    this._mutations = Object.create(null); // 用于存储可调用的 mutation 函数
    this._setupMutations(mutations); // 初始化 mutations
  }
  
  get state() {
    return this._vm._data;
  }

  _setupMutations(mutations) {
    this._mutations = Array.isArray(mutations)
      ? mergeObjects(mutations, true)
      : mutations;
  }
  
  // 提交 Mutation 修改状态 状态变更
  dispatch(type, ...payload) {
    const mutation = this._mutations[type];
    const state = this.state;
    if (!mutation) {
      throw new Error(`[vuex] Unknown action type: ${type}`);
    }
    mutation(state, ...payload);
  }
}

首先将当前对象的 dispatch 方法引用赋值给 dispatch 变量。然后,将 this.dispatch 重新定义为一个新的函数,这个新的函数接收任意数量的参数(由 ...args 表示),并调用 dispatch 函数,同时保证 dispatch 函数内部的 this 上下文仍然指向当前对象。

然后实现我们的 dispatch ,我们将取出对应的 mutation 函数,将 state 传入 mutation 于是 我们可以看这一段

js 复制代码
const mutations = {
  ADD_TODO: (state, todo) => {
    state.todos.push(todo);
  },
};

如上面代码,我们会在这里 (state,payload)=>{} 访问到值并调用,state 指向的就是响应式,后面就是你要传递的值

小结

到这里我们的 mini-vuex 就完成了,感兴趣的朋友可以去实现一个 todo 案例,那么我们总结一下几点,可能面试能说的:

  • Vuex 通过混入的方式实现挂载 this.$store
  • Vuex 内部保存了一份Vue,通过 new Vue 实现数据响应式 所以变更状态,才可以更改视图
相关推荐
子兮曰16 小时前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰16 小时前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万16 小时前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝16 小时前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋17 小时前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
晨米酱17 小时前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
卡布鲁18 小时前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
彧azz19 小时前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
汉堡大王952719 小时前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大19 小时前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端