zoukankan      html  css  js  c++  java
  • 结合 Vue.observable 写一个简易 Vuex

    作为 Vue 全家桶的一员,Vuex 的重要性不言而喻,不管是用来管理状态,还是封装 Controler 都很好用

    不过在一些体量较小的项目中,为了几个简单的状态或者处理函数而引入 Vuex,就像是高射炮打蚊子,大材小用了

    这时候就可以模拟 Vuex,自己写一个简单的 Store, 用来管理状态并实时更新数据

    一、构造函数

    模拟 Vuex 的结构,创建一个 Class

    export default class Store {
      constructor({ states, actions, mutations }) {
        // 状态
        this.states = states || {};
        // 异步函数
        this.actions = actions || {};
        // 同步函数
        this.mutations = mutations || {};
      }
      // 调用 mutations 中的同步函数
      commit = (fun, params) => {};
      // 调用 actions 中的异步函数
      dispatch = (fun, params) => {};
      // 更新 states 的状态
      update = (key, value) => {};
    }

    然后实例化一个 Store

    import Store from './store';
    
    import states from './states';
    import actions from './actions';
    import mutations from './mutations';
    
    const store = new Store({
      states,
      actions,
      mutations,
    });
    
    export default store;

    然后挂到 vue 的原型上,通过 vue.$store 的方式使用,一个高仿 vuex 的架子就搭好了

    // 在 main.js 中引入 Store
    import store from './store/index';
    Vue.prototype.$store = store;

    二、实现操作函数(commit、dispatch、update

    在 Vuex 中,如果需要更新 state 中的状态,需要通过 commit 调用 mutations 中的方法

    而 mutations 的方法都具备一个默认的参数 state,因此 commit 方法可以这么写:

    // 向 mutations 中的传入固定参数 state
    commit = (fun, params) => {
      this.mutations[fun](this.states, params);
    };

    不过由于一些历史遗留问题,我习惯用 this.states 的方式获取 state(这个习惯不好),所以改成了这样:

      commit = (fun, params) => {
        if (fun) {
          this.mutations[fun].call(this, params);
        } else {
          return false;
        }
      };

    类似的 actions 和 update 可以参考 commit 的写法

    三、响应式对象

    目前的 store 有一个致命的问题:state 更新之后并不会即时渲染到视图层

    这时候 Vue 2.6.0 新增的 observable() 就派上用场了

    如果将一个对象作为入参传给 Vue.observable() ,经过处理之后,这个对象在 Vue 内就可以实时更新

    其返回值可以直接用于 render 和 computed 中,并且会在发生改变时触发相应的更新

    于是 Store 的构造函数需要改一改:

      constructor({ states, actions, mutations }) {
        // 状态
        this.states = Vue.observable(states || {});
        // 异步函数
        this.actions = Vue.observable(actions || {});
        // 同步函数
        this.mutations = Vue.observable(mutations || {});
      }

    ⚠️注意:

    假如对象 obj 经过 observable() 处理之后,赋值给了新对象 new_obj

    在 Vue 2.x 中,直接修改 obj 也会触发 new_obj 的更新

    但在 Vue 3.x 中,由于响应机制的变更,只有修改 new_obj 才能触发视图层的更新

    所以在使用 observable() 的时候,最好始终操作使用 observable() 处理后的 new_obj

    四、简单用用

    超低配的 Vuex 已经写好了,上面已经把 store 挂到 Vue 的原型上,所以可以直接使用

    假如 state 中已经存在一个状态 name,在组件中可以通过 computed 去获取

    computed: {
        name() {
          return this.$store.states.name;
        },
    }

    如果需要修改状态,可以通过 $store.update()

    methods: {
        updateName(val) {
            this.$store.update('name', val);
        }  
    }

    或者使用 $store.commit() 调用 mutations 中的方法

    methods: {
        commitName(val) {
            this.$store.commit('handleNameChange', val);
        }  
    }

    大功告成~

  • 相关阅读:
    Netty 源码解读(二)-ChannelPipeline、ChannelHandler、ChannelHandlerContext
    Netty源码解读(一)-服务启动和接收请求源码
    浅谈自动化测试框架开发
    程序运行时环境
    常见的Linux内核线程
    一个好用gdb扩展工具
    使用Qemu模拟Numa机器
    使用qemu的nat方式登录
    2021.32 量化
    2021.31 模型
  • 原文地址:https://www.cnblogs.com/wisewrong/p/11497394.html
Copyright © 2011-2022 走看看