vue的diff算法|青训营笔记

54 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的第9天。虽然这次青训营的课程没有vue相关讲解,但是考虑到大项目是用vue完成的,自己深入学习了vue的diff算法,做此笔记梳理思路。

学习目标

  1. 虚拟DOM如何被渲染函数(h函数)产生 ---手写h函数
  2. diff算法原理 ---手写diff算法
  3. 虚拟DOM如何生成真实DOM ---包含在diff算法中

创建项目

执行npm init

  • 在node开发中使用npm init会生成一个pakeage.json文件,这个文件主要是用来记录这个项目的详细信息的。
  • 它会将我们在项目开发中所要用到的包,以及项目的详细信息等记录在这个项目中,在以后的版本迭代和项目移植的时候会更加的方便。
  • 也是防止在后期的项目维护中误删除了一个包导致的项目不能够正常运行。
  • 使用npm init初始化项目还有一个好处就是在进行项目传递的时候不需要将项目依赖包一起发送给对方,
  • 对方在接受到你的项目之后再执行npm install就可以将项目依赖全部下载到项目里。
  1. 配置项含义:
  • package name: 你的项目名字叫啥
  • version: 版本号
  • description: 对项目的描述
  • entry point: 项目的入口文件(一般你要用那个js文件作为node服务,就填写那个文件)
  • test command: 项目启动的时候要用什么命令来执行脚本文件(默认为node app.js)
  • git repository: 如果你要将项目上传到git中的话,那么就需要填写git的仓库地址(这里就不写地址了)
  • keywirds: 项目关键字(我也不知道有啥用,所以我就不写了)
  • author: 作者的名字(也就是你叫啥名字)
  • license: 发行项目需要的证书(这里也就自己玩玩,就不写了)

执行npm i -S snabbdom

-D表示开发依赖,-S表示生产依赖 由于snabbdom库在git上的文件全是.ts的,没有对应的js文件, 所以使用npm安装其js文件。

安装webpack

snabbdom是DOM库,不能直接在nodejs环境上运行,所以我们需要搭建webpack和webpack-dev-server开发环境。

执行 npm i -D webpack@5 webpack-cli@3 webpack-dev-server@3

  • webpack 是打包代码时依赖的核心内容,
  • webpack-cli 是一个用来在命令行中运行 webpack 的工具。
  • webpack-dev-server这个工具不仅能帮我们打包,还能帮我们起了服务器。还能帮我们自动打开浏览器,还能自动更新
  • 具体功能:
    • 打包
    • 开启一个服务器
    • 实时的自动编译代码,只要我们对源代码做了保存(ctrl+s)
    • webpack-dev-server打包过后生成的bundle.js,不在我们配置的./dist目录下。而是一个暂存在内存中并且被认为是当前网站根目录下(这就需要注意一下将引入的包的目录改成根目录)

手写h()函数

用h函数创建虚拟节点

手写diff算法 --使用最小量更新实现页面渲染

diff算法核心

  1. 实现最小量更新。通过key属性来唯一标识DOM,告诉diff算法,更改前后是同一个DOM节点
  2. 只对于同一个虚拟DOM节点才进行精细化比较,否则就是暴力删除旧的,插入新的 ===>同一个虚拟节点,key属性和选择器相同
  3. 只进行同层比较,不进行跨层比较 即使是同一片虚拟节点,只要跨层了,diff算法也不进行比较 ===>即,当父节点变动时,就算子节点没变,也全部进行暴力删除,再插入新的节点 ===>但父节点变动,子节点不变动的情况在实际运用中非常少

经典diff算法优化策略

四种优化查找:

  1. 新前与旧前
  2. 新后与旧后
  3. 新后与旧前 ===>命中该情况时,要移动新后指针指向的节点,移动到旧后的后面(旧前设为undefined)
  4. 新前与旧后 ===>命中该情况时,要移动新前指针指向的节点,移动到旧前的前面(旧后设为undefined) 从1开始往下找,命中一个则结束,否者继续往下, 若都不命中则循环遍历旧节点来寻找,且寻找找到后,插入到旧前指针之前,若没找到,将新前指针指向的节点插入到旧前指针之前

循环结束语句while(新前>=新后||旧前>=旧后)

如果循环结束

  1. 旧前>=旧后的情况,有新增节点,把新增节点插入旧后
  2. 新前>=新后的情况,有删除节点,且删除的节点为旧前和旧后之间的节点。