Vuejs设计与实现读书笔记-渲染机制
2022-7-4
| 2023-2-19
0  |  0 分钟
password
Created
Feb 19, 2023 04:50 PM
type
Post
status
Published
date
Jul 4, 2022
slug
summary
Vuejs设计与实现读书笔记-渲染机制
tags
Vue源码
Vue
category
Vue
icon

挂载和更新

HTML Attributes VS DOM Properties

HTML Attributes 指的就是定义在 HTML 标签上的属性
当浏览器解析HTML 代码后,会创建一个与之相符的 DOM 元素对象,我们 可以通过 JavaScript 代码来读取该 DOM 对象
这个 DOM 对象会包含很多属性(properties), 这些属性就是所谓的 DOM Properties
有些属性有默认值, 但被修改之后, 两者获取到的值是不同的, 例如input的value属性
 

class

class使用className的性能最优
 

事件处理

事件挂载其实很简单, 就是将on开头的事件去掉on, 首字母大写改小写, 然后再通过addEventListener进行挂载
但是, 当需要更新事件的时候, 则比较麻烦了, 需要将原有的事件移除, 再重新挂载一次事件, 这样的效率显然是比较低的
Vue中使用了一个特殊的invoker来实现事件回调函数的动态挂载
if (!invoker) { invoker = el._vet[key] = (e) => { invoker.value(e) } invoker.value = nextValue el.addEventListener(name, invoker) } else { invoker.value = nextValue }
实现原理是, 调用addEventListener的时候, 其实执行的是一个包装的回调函数, 回调函数本质上执行的是invoker.value, 那么这个时候我们动态的修改invoker.value. 就可以实现动态挂载事件的绑定函数了
因为一个DOM节点上可能会绑定多个同类型的事件回调, 因此需要通过key来区分
 

事件冒泡和更新问题

事件向上冒泡过程中, 可能会因为事件回调中修改了上层组件的状态导致动态绑定或去掉绑定了事件, 从而产生不可预知的奇怪问题
此时, 事件冒泡过程中, 如果时间函数绑定的时间晚于事件发生的事件, 就跳过这个事件函数, 用这个方式来处理
 

简单Diff

  1. 判断新旧节点长度, 遍历短节点, 逐个更新
  1. 如果新节点比较长, 则新增, 旧节点比较长, 则剩余的逐个卸载
 
复用同类型的DOM
增加key比较
 

双端Diff

将新旧元素的双端节点进行相互比较, 找到可以复用的节点, 有则移动节点
如果没有, 则从旧节点中找到新节点中的第一个节点, 并移动此节点到顶部
逐个向下查找
 

快速Diff

借鉴于ivi和inferno, 是目前vue3所使用的diff算法
  1. 找到头尾部不需要处理的节点 预处理
  1. 再去处理新旧需要处理的节点
 
对于剩余的节点
  1. 遍历新节点, 找到新节点对应的旧节点的下标, 没有的标记-1
  1. 求索引的最长递增子序列
  1. 从新节点最后一位开始遍历, 如果是-1则进行insert操作
  1. 如果>-1, 则进行节点移动
  1. 如果在最长递增子序列内, 则不移动
 
Vue
  • Vue源码
  • Vue
  • Vuejs设计与实现读书笔记-组件化Vuejs设计与实现读书笔记-响应式
    目录