Vue响应式原理
-
数据响应式是数据发生变化时,自动运行一些相关的函数。render函数生成虚拟节点,watcher观察,data数据
-
通过object.definproperty将data中数据的每个属性转为一个getter和setter函数,render生成vnode时依赖于data中的数据,会触发getter,记录当前有个render函数用到了我给watcher,---依赖收集。
-
当修改数据时运行setter,通知watcher数据变化了--派发更新,watcher会运行收集的render函数,重新运行render函数,生成vnode。
vue2和vue3的拦截对象操作方式
响应式干了什么?当读取属性时,知道他读了,当给属性赋值时,知道给属性赋值,
-
vue2使用的是object.defineProperty方法,此方法是针对于属性的监听,所以必须深度遍历每一个属性。观察每一个对象,深度遍历对象的所有属性,把所有属性的读取赋值操作变成函数。
-
vue3使用的是proxy,对于整个对象进行监听,能收到对对象的增加修改删除获取操作
-
proxy能够拦截和重新定义对象的所有基本操作,平时使用的获取对象属性值,重新赋值等等都是js提供的语法,会调用对应的基本操作,是一个个函数,例如obj.a ,会运行[Get]函数。使用object.deineproperty,实际上调用的是[DefineOwnProperty]函数,所以他是众多基本操作中的一个,并不会拦截任何基本操作。
diff算法
当组件创建和更新时,vue均会执行内部的update函数,该函数使用render函数生成的虚拟dom树,将新旧两树进行对比,找到差异点,最终更新到真实dom对比差异的过程叫diff,vue在内部通过一个叫patch的函数完成该过程。
在对比时,vue采用深度优先、逐层比较的方式进行比对。 在判断两个节点是否相同时,vue是通过虚拟节点的key和tag来进行判断的具体来说,首先对根节点进行对比,如果相同则将旧节点关联的真实dom的引用挂到新节点上,然后根要更新属性到真实dom,然后再对比其子节点数组;如果不相同,则按照新节点的信息递归创建所有真实dom,同时挂到对应虚拟节点上,然后移除掉旧的dom。
在对比其子节点数组时,vue对每个子节点数组使用了两个指针,分别指向头尾,然后不断向中间靠拢来进行对比,这样做的目的是尽量复用真实dom,尽量少的销毁和创建真实dom。如果发现相同,则进入和根节卢一样的对比流程,如果发现不同,则移动真实dom到合适的位置。这样一直递归的追历下去,直到整棵树完成对比。