Vue源码中的数据代理

2023-06-09,,

直接开讲:

​ 由于这个Vue底层封装的函数太多了,我这里只讲思路不说具体的执行了什么函数.

​ const vm=new Vue({这里写一个data,可以是对象也可以是函数}) 在写这段代码的时候new就已经开始运转了

​ 首先:Vue底层是一个构造函数,然后底层在这个构造函数的原型(prototype)上放了一个_init方法,我们在new的时候,就启动这个方法了,可以知道这个方法的this就是构造函数的实例对象的__proto__,在_init这个方法里面就把this赋值给了一个变量叫做vm,然后往这个vm上面放了一个$options,再把{}赋值给了$options.

​ 其次,延续上面,又调用了一个函数,把vm传过去,在函数里面判断vm.$options.data是否为function,如果是function就涉及到了一个this指向问题,就需要把这个函数的this指向vm,如果是对象那么直接进入下面,下面就是在vm身上添加了一个_data属性,这个再给这个_data赋与vm.$options.data,然后直接将vm.$options.data传入到另外一个函数中,这个函数在这里取个名字叫observe(),到后面会循环使用这个函数,也可以说是一个递归函数;

​ 延续上一段,在另外一个函数中判断传送过来的如果不是一个对象或者说是不是null,满足这其中任意一个条件就return;如果是对象就直接return new Observer(vm.$options.data).

​ (下面这一段先说一下代理vm.$options.data,调用set方法往里面添加对象和数组的情况,也没有重写数组的7个方法)

​ 这里这个new Observer(data)是vue源码中写的一个类,这个类里面会判断data是不是一个数组,是数组就将这个数组里面的所有元素都遍历一遍,然后在传递到observe(item)对象里面,如果一直嵌套就一直回去这个函数,这里需要说一下,如果是数组里面对应索引处是一个普通数据类型就会在observe函数里return掉.这就表示在vue2中数组中的普通数据类型是不会进行数据代理的

​ 上面的这一段说了是数组的情况,这里说一下是对象的情况,如果传入observe(data)是一个对象,那么直接Object.keys().forEach(item=>{在这里调用一个函数,将目标函数和需要代理的key传送过去}),传送过去就会进行一个判断,如果是对象就继续将这个对象传入到observe(item)里面去,直到他不是一个对象为止.

​ 注:如果使用数组的方法去添加值,只用上面的这些逻辑是不够的,刚添加上的数据不会被检测到.那么如果想解决这个问题,就需要在使用push方法时候吧push进去的东西进行一次数据代理.

​ vue对数组方法的重写:①将Array的prototype赋值给一个对象②使用Object.create()方法将创建的这个对象的this指向①中的对象,现在从当前这个对象往上推,其实就有三层原型了.(Array.prototype.proto.proto)然后把这个原型给了data.proto,这里要注意,现在data有了三层原型(data.proto.proto.proto)然后data.proto.__proto__这个对象里面有所有的数组的方法,然后vue给data.__proto__上面有加了7个方法('push','pop','shift','unshift','reserve','sort','splice'),然后调用push,肯定是data调的,然后data的原型第一层就能够拿到重写好的push(),还给push进去的数据进行了代理.

总结:

​ 底层给data中的数据进行了数据代理,不会代理数组中存在的基本数据类型元素,对set方法添加的数据进行判断并代理,给数组方法进行重写并代理数组中存在的对象里面的属性.重写后的数组添加新元素会进行判断并代理

Vue源码中的数据代理的相关教程结束。

《Vue源码中的数据代理.doc》

下载本文的Word格式文档,以方便收藏与打印。