• VUE数组响应式


    vue 为什么没用Object.defineProperty来实现对数组属性的监听

    Object.defineProperty 可以做到对数组的监听,它是支持数组的

    例如

    let array = [1,2,3,4,5]
    
    array.forEach((c,index) => {
        defineReactive(array, index, c)
    })
    function defineReactive(obj, key, val) {
        Object.defineProperty(obj, key, {
            enumerable: true, // 属性可枚举
            configurable: true,
            get() {
                return val;
            },
            set(newVal) {
                if (val === newVal) return
                val = newVal
            }
        })
    }

    我们可以遍历数组,用数组的索引作为 key,来给每一项打上getter/setter。

    Object.defineProperty 有这个能力,但是vue 为什么没用它来实现对数组属性的监听

    原因:

    1. 如果你知道数组的长度,理论上是可以预先给所有的索引设置 getter/setter 的。但是一来很多场景下你不知道数组的长度
    2. 性能问题,数组可能会很长,综合考虑不对数组属性进行监听

    VUE针对数组情况的做法

    重写了数组原型链上的七种方法('push','pop','shift','unshift','splice','sort','reverse'),

    在内部调用了数组的原始方法,最后通过ob.dep.notify()更新视图

      var arrayProto = Array.prototype;
      var arrayMethods = Object.create(arrayProto);
    
      var methodsToPatch = [
        'push',
        'pop',
        'shift',
        'unshift',
        'splice',
        'sort',
        'reverse'
      ];
    
      /**
       * Intercept mutating methods and emit events
       */
      methodsToPatch.forEach(function (method) {
        // cache original method
        var original = arrayProto[method];
        // def给arrayMethods对象添加method属性
        def(arrayMethods, method, function mutator () {
          var args = [], len = arguments.length;
          while ( len-- ) args[ len ] = arguments[ len ];
    
          var result = original.apply(this, args);
          var ob = this.__ob__;
          var inserted;
          switch (method) {
            case 'push':
            case 'unshift':
              inserted = args;
              break
            case 'splice':
              inserted = args.slice(2);
              break
          }
          if (inserted) { ob.observeArray(inserted); }
          // notify change
          // 更新视图
          ob.dep.notify();
          return result
        });
      });  var arrayProto = Array.prototype;
      var arrayMethods = Object.create(arrayProto);
    
      var methodsToPatch = [
        'push',
        'pop',
        'shift',
        'unshift',
        'splice',
        'sort',
        'reverse'
      ];
    
      /**
       * Intercept mutating methods and emit events
       */
      methodsToPatch.forEach(function (method) {
        // cache original method
        var original = arrayProto[method];
        // def给arrayMethods对象添加method属性
        def(arrayMethods, method, function mutator () {
          var args = [], len = arguments.length;
          while ( len-- ) args[ len ] = arguments[ len ];
    
          var result = original.apply(this, args);
          var ob = this.__ob__;
          var inserted;
          switch (method) {
            case 'push':
            case 'unshift':
              inserted = args;
              break
            case 'splice':
              inserted = args.slice(2);
              break
          }
          if (inserted) { ob.observeArray(inserted); }
          // notify change
          // 更新视图
          ob.dep.notify();
          return result
        });
      });

    observeArray 会把数组里面的对象数据变成是可侦测的响应式数据

  • 相关阅读:
    隐马尔可夫模型 机器学习
    机器学习——EM算法与GMM算法
    机器学习——贝叶斯算法
    SVM算法 机器学习
    机器学习——谱聚类
    机器学习——Canopy算法
    机器学习——密度聚类
    Identity(身份)
    hyperledger fabric 结构模型学习
    fabric v1.1.0部署准备工作
  • 原文地址:https://www.cnblogs.com/wangxirui/p/15785309.html
Copyright © 2020-2023  润新知