• 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 会把数组里面的对象数据变成是可侦测的响应式数据

  • 相关阅读:
    计数排序
    桶排序
    给定两个数组,这两个数组是排序好的,让你求这两个数组合到一起之后第K大的数。
    leetcode349 python3 112ms 求两个数组的交集
    leetcode852 C++ 20ms 找最高峰 序列先增后减
    leetcode665 C++ 36ms 非递减数列 这题没啥意思
    leetcode414 C++ 4ms 第三大的数字
    C++ 堆排序 以及用堆排序解决topk问题
    leetcode628 python3 124ms 三个数字的最大乘积
    leetcode26 C++ 20ms 删除排序数列中的重复元素
  • 原文地址:https://www.cnblogs.com/wangxirui/p/15785309.html
Copyright © 2020-2023  润新知