Vue

变化监测

Object.defineProperty
Object监听

Vue底层原理_子节点

在计算属性中直接修改可以吗?不可以会发出警告⚠,通过setter修改会触发响应式

Array

Vue底层原理_HTML_02

Vue底层原理_子节点_03

push、pop、shift、unshift、splice、sort、reverse

Vue底层原理_HTML_04

虚拟DOM与Diff算法

Vue底层原理_Vue_05

VNode

在Vue.js中,VNode(虚拟节点)是Vue用于描述DOM节点的轻量级JavaScript对象。VNode是Vue实现高效渲染和更新的核心机制之一。通过VNode,Vue可以在内存中进行DOM操作,避免直接操作真实DOM,从而提高性能。

Vue底层原理_Vue_06

VNode的基本结构

VNode是一个普通的JavaScript对象,通常包含以下属性:

  • tag: 标签名,如divspan等。
  • data: 包含节点属性、事件监听器等信息的对象。
  • children: 子节点数组,每个子节点也是一个VNode。
  • text: 文本节点的内容。
  • elm: 对应的真实DOM节点。
  • key: 用于优化列表渲染的唯一标识符。
{
  tag: 'div',
  data: {
    attrs: {
      id: 'app'
    },
    on: {
      click: handleClick
    }
  },
  children: [
    {
      tag: 'span',
      text: 'Hello World'
    }
  ],
  elm: null,
  key: 'uniqueKey'
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
VNode的创建

在Vue中,VNode通常通过createElement函数(也称为h函数)创建。createElement函数接收标签名、属性对象和子节点作为参数,返回一个VNode对象。

import { createElement } from 'vue';

const vnode = createElement('div', {
  attrs: {
    id: 'app'
  },
  on: {
    click: handleClick
  }
}, [
  createElement('span', null, 'Hello World')
]);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
VNode的渲染

VNode最终会被渲染为真实DOM节点。Vue通过patch函数将VNode与真实DOM进行比较,并根据差异进行更新patch函数会递归地处理VNode的children,确保整个DOM树与VNode树保持一致。

function patch(oldVnode, vnode) {
  // 比较新旧VNode,更新真实DOM
}
  • 1.
  • 2.
  • 3.
VNode的优化

Vue通过VNode的key属性来优化列表渲染。当列表中的元素顺序发生变化时,Vue会根据key来识别哪些元素可以复用,从而减少不必要的DOM操作。

const list = [
  { id: 1, text: 'Item 1' },
  { id: 2, text: 'Item 2' }
];

const vnodes = list.map(item => createElement('li', { key: item.id }, item.text));
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
VNode的生命周期

VNode在创建、更新和销毁时会触发相应的生命周期钩子。这些钩子可以用于执行一些自定义逻辑,如数据获取、事件绑定等。

const vnode = createElement('div', {
  hook: {
    insert(vnode) {
      console.log('VNode inserted into DOM');
    },
    update(oldVnode, vnode) {
      console.log('VNode updated');
    },
    destroy(vnode) {
      console.log('VNode destroyed');
    }
  }
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

通过理解VNode的结构和生命周期,可以更好地掌握Vue的渲染机制,并编写出更高效的Vue应用。

Diff算法

 Vue2&Vue3 Diff算法Vue中Diff算法比较两棵虚拟 DOM 树:旧的 VNode 和新的 VNode。通过这种方式,Vue 能够找出发生变化的部分,并仅对这些部分进行真实 DOM 的更新,从而提高性能。

patch

同层比较不是同类标签直接替换,同类标签且新旧虚拟节点相同就直接返回,不同的话就:

  • 文本节点替换:如果VNode是文本节点,如果不同则把oldVNode里文本替换跟VNode的文本一样
  • 新增子节点:新的VNode中有而旧的oldVNode中没有子节点,就在旧的oldVNode中新增。
  • 删除子节点:新的VNode中没有而旧的oldVNode中有子节点,就从旧的oldVNode中删除。
  • 更新节点:新的VNode和旧的oldVNode中都有子节点,就以新的VNode为准,更新旧的oldVNode。 更新流程(updateChildren):双端比较+key复用

Vue3中BlockTree如何理解?

Vue底层原理_HTML_07

模板编译

在标签中除了写一些原生HTML的标签,我们还会写一些变量插值,或者写一些Vue指令,如v-on、v-if等。而这些东西都是在原生HTML语法中不存在的,不被接受的。Vue会把用户在标签中写的类似于原生HTML的内容进行编译,把原生HTML的内容找出来,再把非原生HTML找出来,经过一系列的逻辑处理生成渲染函数,而render函数会将模板内容生成对应的VNode。

Vue底层原理_子节点_08

 AST

模板解析阶段:将一堆模板字符串用正则等方式解析成抽象语法树AST;优化阶段:遍历AST,找出其中的静态节点,并打上标记;代码生成阶段:将AST转换成渲染函数;

Vue底层原理_HTML_09

Vue底层原理_HTML_10

模板解析其实就是根据被解析内容的特点使用

正则等

方式将有效信息解析提取出来,根据解析内容的不同分为

HTML解析器,文本解析器和过滤器解析器

。而文本信息与过滤器信息又存在于HTML标签中,所以在解析器主线函数

parse中先调用HTML解析器

parseHTML 函数对模板字符串进行解析,

如果在解析过程中遇到文本或过滤器信息则再调用相应的解析器进行解析

,最终完成对整个模板字符串的解析。

生命周期

Vue底层原理_Vue_11

Vue底层原理_Vue_12

Vue底层原理_子节点_13

实例方法
过滤器(弃用)

Vue底层原理_子节点_14

Vue底层原理_子节点_15

Vue底层原理_HTML_16

指令篇

Vue底层原理_子节点_17

内置组件
keep-alive

Vue底层原理_子节点_18