ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

vue双向数据绑定数组失效,源码修改

2022-08-15 10:35:02  阅读:187  来源: 互联网

标签:__ vue Observer 绑定 ob value 源码 数组 observeArray


我们都知道在vue中直接修改数组下标来修改数据,是不能触发vue的更新机制的,但是当你发现随着项目代码越来越多,你的$set会越来越多,这样会让你的代码可读性、维护性越来越差

修改vue源码,让vue支持修改下标触发更新

function observe (value, asRootData) {
  if (!isObject(value) || value instanceof VNode) {
     return
   }
   var ob;
   if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
     ob = value.__ob__;
   } else if (
     shouldObserve &&
     !isServerRendering() &&
     (Array.isArray(value) || isPlainObject(value)) &&
     Object.isExtensible(value) &&
     !value._isVue
   ) {
     ob = new Observer(value); // 看这里,那么Observer又是什么呢?
   }
   if (asRootData && ob) {
     ob.vmCount++;
   }
   return ob
 }
// 我们继续看
var Observer = function Observer (value) {
  this.value = value;
   this.dep = new Dep();
   this.vmCount = 0;
   def(value, '__ob__', this);
   // 我们看到如果是数组,则执行this.observeArray,那么这个方法又做了什么呢?
   if (Array.isArray(value)) {
     if (hasProto) {
       protoAugment(value, arrayMethods);
     } else {
       copyAugment(value, arrayMethods, arrayKeys);
     }
     this.observeArray(value);
   } else {
   // 看完上面的observeArray,我们继续看this.walk又做了什么?
     this.walk(value);
   }
 };
 // 原来这个observeArray,其实就是个递归,如果是数组就遍历,然后继续执行observe -> new Observer
 Observer.prototype.observeArray = function observeArray (items) {
  for (var i = 0, l = items.length; i < l; i++) {
     observe(items[i]);
   }
 };
 Observer.prototype.walk = function walk (obj) {
   var keys = Object.keys(obj);
   for (var i = 0; i < keys.length; i++) {
     defineReactive$$1(obj, keys[i]);
   }
 };
// 我们继续看defineReactive$$1,又做了什么?
// 原来他的庐山真面目就是defineProperty,这下我们都明白了吧
 function defineReactive$$1 (
    obj,
    key,
    val,
    customSetter,
    shallow
  ) {
    ...
    Object.defineProperty(obj, key, {
      enumerable: true,
      configurable: true,
      get: function reactiveGetter () {
        var value = getter ? getter.call(obj) : val;
        ...
      },
      set: function reactiveSetter (newVal) {
        ...
        dep.notify();
      }
    });
  }

原来在vue源码中,只对Object的各个key进行了监听,对数组下标并没有,那么我们如何修改呢?

var Observer = function Observer (value) {
  this.value = value;
   this.dep = new Dep();
   this.vmCount = 0;
   def(value, '__ob__', this);
   // 我们看到如果是数组,则执行this.observeArray,那么这个方法又做了什么呢?
   if (Array.isArray(value)) {
     if (hasProto) {
       protoAugment(value, arrayMethods);
     } else {
       copyAugment(value, arrayMethods, arrayKeys);
     }
     this.observeArray(value);
     this.walk(value); // 我们只需要在这里添加这行,就可完成对下标的监听
   } else {
   // 看完上面的observeArray,我们继续看this.walk又做了什么?
     this.walk(value);
   }
 };

完成以上修改后,我们再直接修改数组下标,页面也会进行更新

以上内容是我自己平时写项目得到的想法(不想写那么多$set),那我这个菜鸡能想到,尤大就想不到吗?
下面贴上尤大对此处的回答https://github.com/vuejs/vue/issues/8562

 

 看到了吧?因为性能!我们可以想数组也是对象,不过比较特殊,数组的下标是对象的key,那么如果是一个对象数组,甚至说层级嵌套更加深的数据,是不是监听每一个下标的话,会非常庞大,我使用了100个循环来验证,结果是如果监听数组下标的话渲染时间要比不监听的时候慢了4倍还不止!
所以,这个监听数组下标是可以实现,也可以让你的代码看起来更加优雅,但是如果项目特别小,或者只是自己的测试demo的话,可以这么玩,如果是公司项目的话,个人建议还是保持原样,因为涉及到性能!

标签:__,vue,Observer,绑定,ob,value,源码,数组,observeArray
来源: https://www.cnblogs.com/huoshengmiao/p/16587328.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有