首页 vue模板渲染及diff算法
文章
取消

vue模板渲染及diff算法

组件如何渲染

初次渲染过程

  • 解析模版为render函数(或在开发环境已经完成,vue-loader)
  • 触发响应式,监听 data 属性 getter setter
  • 执行 render 函数,生成 vnodepatch(elem, vnode)

更新过程

  • 修改 data, 触发setter(此前在getter中已被监听)
  • 重新执行 render函数,生成 newVnode
  • patch(vnode, newVnode)

异步渲染 $nextTick

  • 汇总 data 的修改,一次性更新视图
  • 减少 DOM 操作次数,提高性能

虚拟 DOM 和 diff

  • vdom 是实现 vue 和 React 的重要基石
  • diff 算法是vdom 中最核心、最关键的部分

用JS模拟DOM结构

1
2
3
4
5
6
<div id="div1" class="container">
    <p>vdoom</p>
    <ul style="font-size:20px">
        <li>a</li>
    </ul>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
    tag: 'div',
    props: {
        className: 'container', 
        id: 'div1'
    },
    children: [
        {
            tag: 'p',
            children 'vdom'
        },
        {
            tag: 'ul',
            props: { style: 'font-size: 20px' },
            children: [
                {
                    tag: 'li',
                    children: 'a'
                }
                // ....
            ]
        }
    ]
}

下面用js将dom字符转化为DOM结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function parseHTMLToVNode(htmlString) {
  // 创建一个临时的DOM元素
  const tempDiv = document.createElement('div');
  tempDiv.innerHTML = htmlString.trim();

  // 递归解析节点
  function parseNode(node) {
    if (node.nodeType === 3) { // 文本节点
      return node.nodeValue;
    }
    if (node.nodeType === 1) { // 元素节点
      const vnode = {
        tag: node.tagName.toLowerCase(),
        attrs: {},
        children: []
      };

      // 解析属性
      for (let attr of node.attributes) {
        vnode.attrs[attr.name] = attr.value;
      }

      // 递归解析子节点
      for (let childNode of node.childNodes) {
        vnode.children.push(parseNode(childNode));
      }

      return vnode;
    }
  }

  return parseNode(tempDiv.firstChild);
}

// 测试
const htmlString = '<div id="text" class="content">这是一段内容<span style="color: red">我是标会的内容</span>不知道是什么内容<p>1234567</p>哈哈哈哈</div>';
const vdom = parseHTMLToVNode(htmlString);
console.log(vdom); 
// {"tag":"div","attrs":{"id":"text","class":"content"},"children":["这是一段内容",{"tag":"span","attrs":{"style":"color: red"},"children":["我是标会的内容"]},"不知道是什么内容",{"tag":"p","attrs":{},"children":["1234567"]},"哈哈哈哈"]}

通过 snabbdom学习 vdom

Vue2 Vue3 React 三者 diff 算法有何区别?

  • vue2 - 双端比较
  • vue3 - 最长递增子序列
  • react - 仅右移
转摘分享请注明出处

react基础知识

浏览器输入url发生了什么