zoukankan      html  css  js  c++  java
  • Vue源码学习之数据初始化

    首发地址:CJWbiu's Blog

      在这里思考一个问题,使用Vue的时候需要在创建Vue实例时传入一个option,这里包含了我们定义的props、methods、data等。而在methods的方法中获取data中的key值都是直接通过this.key获取option对象中的methods中的定义的方法如何通过this访问到data中的数据呢?

    let vue = new Vue({
        el: '#app',
        methods: {
          say() {
            console.log(this.msg)
          }
        },
        data: {
          msg: 'jjjjj'
        }
    })

      一开始我想是将datamethods中的数据全都挂载到了vm上,然而Vue实例上有methods中定义的方法,却没有data中的属性,data中的数据全部存储在vm._data中,通过this.key访问其实是this._data.key,Vue在这里做了一层代理,通过defineProperty设置了vm的getter和setter,而methods中的方法在initMethods方法中将其中的this绑定到了vm上,这样methods中方法访问的this也就指向了_data。 


      下面是参照源码相关逻辑的简化代码:

    function MyVue(option) {
      this._init(option);
    }
    
    MyVue.prototype._init = function(option) {
      const vm = this; 
      vm.$options = option; //源码在此做了对子组件option的合并处理
      if(vm.$options.methods) initMethods(vm, vm.$options.methods); //源码中还有对props的处理,data、props、methods都会做查重处理,不能有相同的属性名
      if(vm.$options.data) initData(vm);
    }
    
    function initMethods(vm, methods) {
      const props = vm.$options.props
      for (const key in methods) {
        vm[key] = methods[key].bind(vm);  //将methods上的方法挂载到vm上并将方法中所有的this指向vm,通过下面的proxy就可以访问到_data上的属性
      }
    }
    
    function initData(vm) { //将data上数据复制到_data并遍历所有属性添加代理
      vm._data = vm.$options.data;
      const keys = Object.keys(vm._data); 
      let i = keys.length;
      while(i--) {  
        const key = keys[i];
        proxy(vm, `_data`, key);
      }
    }
    function proxy(target, sourceKey, key) {
      let sharedPropertyDefinition = {};
      sharedPropertyDefinition.get = function proxyGetter () {
        return this[sourceKey][key]
      }
      sharedPropertyDefinition.set = function proxySetter (val) {
        this[sourceKey][key] = val
      }
      Object.defineProperty(target, key, sharedPropertyDefinition)  //一层代理,每次访问this[key]时代理到this._data[key]
    }
    
    let app = new MyVue({
      methods: {
        say: function() {
          console.log(this.msg + this.age);
        }
      },
      data: {
        msg: 'jjj',
        age: 33
      }
    })
    app.say(); //jjj33
  • 相关阅读:
    考研机试 5.反序输出
    考研机试 4.代理服务器
    考研机试 3.约数的个数
    考研机试 8.整数拆分
    考研机试 6.手机键盘
    考研机试 2.成绩排序
    监督学习与非监督学习的区别
    关于调整input里面的输入光标大小
    JS读取cookie(记住账号密码)
    html嵌套规则
  • 原文地址:https://www.cnblogs.com/cjw-ryh/p/10708098.html
Copyright © 2011-2022 走看看