【Vue源码】图解 diff算法 与 虚拟DOM 您所在的位置:网站首页 vue中的虚拟dom和diff算法 【Vue源码】图解 diff算法 与 虚拟DOM

【Vue源码】图解 diff算法 与 虚拟DOM

2024-07-12 23:24| 来源: 网络整理| 查看: 265

文章目录 0. 文章结构预览 0.1 虚拟DOM如何被渲染函数(h函数)产生 0.2 diff算法的原理 0.3 虚拟DOM如何通过diff变成真正的DOM 1. 介绍 1.1 diff算法 1.2 虚拟DOM 1.3 关系——diff是发生在虚拟DOM上的 2. snabbdom 简介 及 准备工作 2.1 简介 2.2 搭建初始环境 1. 安装snabbdom 2. 安装webpack5并配置 3. 复制官方demo Example 3. h函数的介绍与使用 3.1 介绍 3.2 使用h函数 创建虚拟节点 3.3 使用patch函数 将虚拟节点上DOM树 3.4 h函数嵌套使用,得到虚拟DOM树(重要) 4. 手写h函数 vnode.js h.js index.js 效果展示 5. 手写diff算法准备 5.1 diff算法原理 5.2 手写diff预备 5.2.1 源码中如何定义“同一个节点” 5.2.2 源码中创建子节点,需要递归 6. 手写diff——首次上DOM树`patch(container, myVnode1)` 6.0 DOM 预备知识 6.0.1 Node.insertBefore() 6.0.2 Node.appendChild() 6.0.3 Element.tagName 6.0.4 Node.removeChild 6.0.5 document.createElement 6.1 patch.js 6.2 createElement.js 6.3 index.js 6.4 展示效果 7. 处理新旧节点 是同一个节点 的情况 7.1 分析 7.2 实现 新旧节点text不同情况 7.2.1 patch.js 7.2.3 patchVnode.js 7.2.2 index.js 7.3 展示 8. 分析 diff算法 更新子节点操作(重要) 8.1 循环四种命中查找 1. 比较 ① 新前newStart 与 旧前oldStart 2. 比较 ② 新后newEnd 与 旧后 oldEnd 3. 比较 ③ 新后newEnd 与 旧前oldStart 命中③复杂情况举例——倒序 4. 比较 ④ 新前newStart 与 旧后oldEnd 5. 四种都没命中 遍历oldVnode中的key 8.2 循环结束 9. 手写diff更新子节点操作 patchVnode.js updateChildren.js

来自尚硅谷的课程笔记 课程链接 尚硅谷邵山欢(考拉老师)Vue之虚拟DOM和diff算法 加入大量的注释以及大量改写,新增很多插图解释diff算法 第八章仔细说明了老师说的一些比较含糊的地方 源码链接 https://gitee.com/ykang2020/vue_learn

0. 文章结构预览

在这里插入图片描述

0.1 虚拟DOM如何被渲染函数(h函数)产生

目标:手写h函数

0.2 diff算法的原理

目标:手写diff算法

0.3 虚拟DOM如何通过diff变成真正的DOM 1. 介绍 1.1 diff算法

精细化比较 在这里插入图片描述

1.2 虚拟DOM

本课程不涉及DOM如何变成虚拟DOM 这属于模板编译原理范畴 但是虚拟节点变成DOM节点在diff中可以做到 在这里插入图片描述

1.3 关系——diff是发生在虚拟DOM上的

新虚拟DOM和旧虚拟DOM进行diff(精细化比较),算出应该如何最小量更新,最后反映到真正的DOM上

在这里插入图片描述

2. snabbdom 简介 及 准备工作 2.1 简介

snabbdom(瑞典语,“速度”)是著名的虚拟DOM库,是diff算法的鼻祖 Vue源码借鉴了snabbdom 源码使用TypeScript写的https://github.com/snabbdom/snabbdom 从npm下载的是build出来的JavaScript版本

npm install -D snabbdom 2.2 搭建初始环境 1. 安装snabbdom cnpm install -S snabbdom

在这里插入图片描述

2. 安装webpack5并配置 cnpm i -D webpack@5 webpack-cli@3 webpack-dev-server@3

配置webpack5

module.exports = { // webpack5 不用配置mode // 入口 entry: "./src/index.js", // 出口 output: { // 虚拟打包路径,文件夹不会真正生成,而是在8080端口虚拟生成 publicPath: "xuni", // 打包出来的文件名 filename: "bundle.js", }, // 配置webpack-dev-server devServer: { // 静态根目录 contentBase: 'www', // 端口号 port: 8080, }, }; 3. 复制官方demo Example

src/index.js

import { init, classModule, propsModule, styleModule, eventListenersModule, h, } from "snabbdom"; const patch = init([ // Init patch function with chosen modules classModule, // makes it easy to toggle classes propsModule, // for setting properties on DOM elements styleModule, // handles styling on elements with support for animations eventListenersModule, // attaches event listeners ]); const container = document.getElementById("container"); const vnode = h("div#container.two.classes", { on: { click: function () { } } }, [ h("span", { style: { fontWeight: "bold" } }, "This is bold"), " and this is just normal text", h("a", { props: { href: "/foo" } }, "I'll take you places!"), ]); // Patch into empty DOM element – this modifies the DOM as a side effect patch(container, vnode); const newVnode = h( "div#container.two.classes", { on: { click: function () { } } }, [ h( "span", { style: { fontWeight: "normal", fontStyle: "italic" } }, "This is now italic type" ), " and this is still just normal text", h("a", { props: { href: "/bar" } }, "I'll take you places!"), ] ); // Second `patch` invocation patch(vnode, newVnode); // Snabbdom efficiently updates the old view to the new state

在这里插入图片描述

3. h函数的介绍与使用 3.1 介绍

用来产生虚拟节点(vnode) 在这里插入图片描述 虚拟节点vnode的属性

{ children: undefined// 子元素 数组 data: { } // 属性、样式、key elm: undefined // 对应的真正的dom节点(对象),undefined表示节点还没有上dom树 key: // 唯一标识 sel: "" // 选择器 text: "" // 文本内容 } 3.2 使用h函数 创建虚拟节点 // 创建虚拟节点 var myVnode1 = h('a', { props: { href: 'https://www.baidu.com' } }, 'YK菌') console.log(myVnode1)

在这里插入图片描述

3.3 使用patch函数 将虚拟节点上DOM树 // 创建patch函数 const patch = init([ classModule, propsModule, styleModule, eventListenersModule, ]); // 创建虚拟节点 var myVnode1 = h( "a", { props: { href: "https://www.baidu.com", target: "_blank" } }, "YK菌" ); // 让虚拟节点上树 let container = document.getElementById("container"); patch(container, myVnode1);

在这里插入图片描述

3.4 h函数嵌套使用,得到虚拟DOM树(重要)

在这里插入图片描述

const myVnode3 = h('ul', [ h('li', '苹果'), h('li', '香蕉'), h('li', '西瓜'), h('li', '番茄'), ]) // 让虚拟节点上树 let container = document.getElementById("container"); patch(container, myVnode3);

在这里插入图片描述

const myVnode3 = h('ul', [ h('li', '苹果'), h('li', [ h('div', [ h('p', '香蕉'), h('p', '草莓') ]) ]), h('li', h('span','西瓜')), h('li', '番茄'), ]) <


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有