最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Vuex原理理解及简单实现

    正文概述 掘金(实在想不出什么名字)   2020-12-03   507

    Vuex是什么?

    • 官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
    • 个人理解:Vuex就是用来进行组件之间进行数据交换的第三方 “仓库”,组件可以把想要共享的数据存放在这里面,别的组件想要的之后直接调取即可。

    Vuex原理理解

    Vuex实现

    
    let Vue = null; // 用一个全局变量接收 Vue.use() 传过来的vue函数
    function install(_Vue){
      Vue = _Vue;
    
      // 混入一个对象
      Vue.mixin({
        beforeCreate() {
          // 这里的this是当前组件(要实现的功能是给每一个组件都添加 $store 属性,值就是 创建的 Store 实例)
          // console.log(this);
          if(this.$options.store) {
            // console.log('我是根')
            this.$store = this.$options.store;
          } else if(this.$parent) {
            // console.log('我不是祖根尖')
            this.$store = this.$parent.$store;
          }
        }
      });
    }
    
    class Store{
      constructor(options) {
        // options配置有 state、mutations、getters等
        // 其中 state 是响应式的,借助vue实例的data是响应式的
        let vm = new Vue({
          data: {
            state: options.state
          }
        });
        this.state = vm.state;
    
        // mutations 存放的是方法,且方法中的this是当前Store实例
        this.mutations = {};
        let mutations = options.mutations || {};
        Object.keys(mutations).forEach(mutation => {
          // 这个箭头函数中的this是Store实例
          this.mutations[mutation] = (param) => {
            // 这里的this仍然是当前 Sotre 的实例
            // 为什么不直接 this.mutations[mutation](param) 呢?
            // 因为是死递归,会造成内存泄漏
            mutations[mutation].call(this, this.state,param); // 通过 call 强制改变方法中的this指向
          };
        });
    
        // actions 中存放的也是方法,与mutations不同的是,它里面的函数接收的第一个参数是当前 Store 实例
        this.actions = {};
        let actions = options.actions || {};
        Object.keys(actions).forEach(action => {
          // this.actions[action] = actions[action].bind(this,this);  // 这里是通过 bind来改变函数中this的指向,但是不建议,因为这样写的话,那么在执行某一个action方法时就可以传递多个参数,可是action默认是最多接收两个参数的
    
          this.actions[action] = (param) => {
            // 这里的this仍然是当前 Sotre 的实例
            // 为什么不直接 this.mutations[mutation](param) 呢?
            // 因为是死递归,会造成内存泄漏
            actions[action].call(this, this,param); // 通过 call 强制改变方法中的this指向
          };
        });
    
        // getters 存储的也是函数,但是每个函数都要return 一个值,而且这个值还是响应式的,这就需要用到数据劫持
        this.getters = {};
        let getters = options.getters || {};
        Object.keys(getters).forEach(getter => {
          Object.defineProperty(this.getters, getter, {
            get: () => {
              // console.log(this, this.getters);
              // 调用 getters 是不需要传参的,但是默认第一个参数是 this.state
              return getters[getter].call(this, this.state);
            }
          });
        });
      }
      // 触发 mutations 中的方法是通过 commit
      commit(type, param) {
        console.log(this.mutations);
        this.mutations[type](param)
      }
      // 触发 actions 中的方法是通过 dispatch
      dispatch(type, param){
        this.actions[type](param);
      }
    }
    
    // 辅助函数: 不管是 mapState 还是其他辅助函数,最后都是在响应的{}中通过展开运算符获取其值,所以这些函数执行完之后应该是返回一个对象
    
    // 所有辅助函数只考虑传的值是数组的情况
    export function mapState(ary){
      let obj = {}; // obj每一个属性的值都是一个函数,并且函数中返回的是 store.state的值
      ary.forEach(item => {
        // 要让obj的属性对应上ary的每一项,但是属性值是 Store实例上的state
        obj[item] = function(){
         console.log(this) // =>当前使用这个属性的组件
         return this.$store.state[item]
        }
      });
      console.log(obj);
      return obj;
    };
    
    export function mapGetters(ary){
      let obj = {}; // obj每一个属性的值都是一个函数,并且函数中返回的是 store.state的值
      ary.forEach(item => {
        // 要让obj的属性对应上ary的每一项,但是属性值是 Store实例上的state
        obj[item] = function(){
         return this.$store.getters[item]
        }
      });
      return obj;
    };
    
    export function mapMutations(ary) {
      let obj = {};
      ary.forEach(item => {
        obj[item] = function(param){
          this.$store.commit(item,param)
        }
      });
      return obj;
    };
    
    export function mapActions(ary) {
      let obj = {};
      ary.forEach(item => {
        obj[item] = function(param) {
          this.$store.dispatch(item, param);
        }
      })
    }
    
    export default {
      Store,
      install
    }
    

    !注意:这里只是简单实现Vuex的一些基本功能,方便我自己理解Vuex的功能和使用。


    起源地下载网 » Vuex原理理解及简单实现

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元