最近死磕了一段时间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中的数组我们命名为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()和设置()美元。