从vue源码解析Vue.set()和设置()美元。

  

  

最近死磕了一段时间vue源码,想想觉得还是要输出点东西,我们先来从vue提供的Vue.set()和设置()美元。这两个api看看它内部是怎么实现的。

  

<强> Vue.set()和设置()美元。应用的场景

  

平时做项目的时候难免不会对数组或者对象进行这样的骚操作操作,结果发现,咦~ ~,他喵的,怎么页面没有重新渲染。

        const vueInstance=new Vue ({   数据:{   加勒比海盗:[1,2],   其中obj1: {   答:3   }   }   });   vueInstance $ data。arr [0]=3;//这种骚操作页面不会重新渲染   vueInstance data.obj1美元。b=3;//这种骚操作页面不会重新渲染      

查了一下官方文档,发现人家早就说过这种情况

  

Vue.set()向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新属性,因为Vue无法探测普通的新增属性(比如this.myObject。newProperty='嗨')

  

所以按照官网的写法,我们应该使用下面这种写法:

        Vue.set (vueInstance $ data。加勒比海盗0 3);//这样操作数组可以让页面重新渲染   vueInstance。(vueInstance。美元数据。加勒比海盗0 3);//这样操作数组也可以让页面重新渲染   Vue.set (vueInstance $ data。其中obj1 b 3);//这样操作对象可以让页面重新渲染   vueInstance。(vueInstance。美元数据。其中obj1 b 3);//这样操作对象也可以让页面重新渲染   
     

<强> Vue.set()和设置()美元。实现原理

  

是时候看一波这两个api的源码了,我们先来看看Vue.set()的源码:

        进口组{}“. ./观察者/指数”   …   Vue。=集合   …      

再来看看<代码>。美元组()的源码:

        进口组{}“. ./观察者/指数”   …   Vue.prototype。美元=集合   …      

结果我们发现<代码> Vue.set()和设置()美元。这两个api的实现原理基本一模一样,都是使用了一组函数这里函数是从. ./观察者/索引文件中导出的,区别在于Vue.set()是将设置函数绑定在Vue构造函数上,这个。美元组()是将设置函数绑定在Vue原型上。

  

接下来我们根据. ./观察者/索引中找组出函数:

        函数集(目标:Array|对象、关键:任何val:任何):{   如果(process.env。NODE_ENV !==?,   (isUndef(目标)| | isPrimitive(目标))   ) {   警告('不能设置活性属性alt="从vue源码解析Vue.set()和设置()美元。">

  

我们接着往下看:

        如果(process.env。NODE_ENV !==?,   (isUndef(目标)| | isPrimitive(目标))   ) {   警告('不能设置活性属性>   如果(Array.isArray(目标),,isValidArrayIndex(关键)){   目标。长度=Math.max(目标。长度,键)   目标。接头(1,关键val)   返回瓦尔   }      

这里实际就是修改数组时调用集方法时让我们能够触发响应的代码,不过在分析这段代码之前我们来看看vue中的数组实际上是长什么样的。下图分别是vue中的数组和普通的js数组:

  

从vue源码解析Vue.set()和设置()美元。

  

从vue源码解析Vue.set()和设置()美元。

  

vue中的数组我们命名为arrVue, js中的普通数组命名为arrJs。其实我们平时调用普通数组的推动,流行等方法是调用的原数组型上面定义的方法,从图中我们可以看出arrJs的原型是指向数组中。原型,也就是说arrJs。__proto__==数组。原型。

  

但是在vue的数组中,我们发现arrVue的原型其实不是指向的Array.prototype,而是指向的一个对象(我们这里给这个对象命名为arrayMethods) .arrayMethods上面只有7个,流行等方法,并且arrayMethods的原型才是指向的数组。原型,所以我们在vue中调用数组的推动,流行等方法时其实不是直接调用的数组原型给我们提供的推动,流行等方法,而是调用的arrayMethods给我们提供的推动,流行等方法.vue为什么要给数组的原型链上面加上这个arrayMethods呢?这里涉及到了vue的数据响应的原理,我们这篇文章暂时不谈论数据响应原理的具体实现。这里你可以理解成vue在arrayMethods对象中做过了特殊处理,如果你调用了arrayMethods提供的推动,流行等7个方法,那么它会触发当前收集的依赖(这里收集的依赖可以暂时理解成渲染函数),导致页面重新渲染。换句话说,对于数组的操作,我们只有使用arrayMethods提供的那7个方法才会导致页面渲染,这也就解释了为什么我们使用vueInstance $ data。arr [0]=3;时不会导致页面出现渲染。

从vue源码解析Vue.set()和设置()美元。