虚拟DOM实现原理
什么是虚拟DOM
Virtual Dom(虚拟DOM)是由普通的js对象来描述DOM对象,因为不是真实的DOM对象,因此被称为虚拟DOM
为什么使用虚拟DOM
- DOM对象成员多,创建dom对象成本高
- 手动操作dom比较麻烦,要考虑浏览器兼容性问题
- 好处就是当状态改变时不需要立即更新dom,只需要创建一个虚拟数来描述dom,虚拟dom内部弄清楚如何有效更新dom
- 为了简化视图的操作出现了各种mvvm框架,解决了视图和状态的同步问题,也就是当数据发生变化,更新视图,当视图发生变化更新数据。
- 为了简化视图的操作我们可以使用模板引擎,但是模板引擎没有解决跟踪状态变化的问题(当数据发生了变化后,无法获取上一次的状态,只有将页面上的元素删除,然后在重新创建,这时页面有刷新的问题,同时频繁操作
Dom
,性能也会非常低),于是Virtual Dom
出现了。
虚拟dom的思想是先控制数据再到视图,但是数据状态不是通过diff比对,他会对新旧虚拟dom节点,然后找到两者不同,将不同节点重新渲染
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MH1HOQM8-1623111036972)(./images/虚拟DOM1.png)]
虚拟dom的作用
维护视图和状态的关系(虚拟dom会记录状态的变化,只需要更新状态变化的内容就可以了)
复杂视图下提升渲染性能
简单案例适合dom操作实现
let div=document.querySelector('#app')
let btn=document.querySelectory('#btn')
btn.onclick=function(){
div.textContent='Hello World'
}
视图比较简单不需要使用虚拟dom
vue中虚拟dom生成真实dom的过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EbQOtKKS-1623111036974)(./images/虚拟DOM的生成.png)]
Snabbdom基本使用
创建项目
打包工具为了方便使用,使用了parcel
,你也可以使用webpack
.
下面创建项目,并安装parcel
//创建项目目录
md snabbdom-demo
// 进入项目目录
cd snabbdom-demo
// 创建package.json
npm init -y
//本地安装parcel
npm install parcel-bundler
配置package.json
中的scripts
"srcipts":{
"dev":"parcel index.html --open" , //open打开浏览器
"build":"parcel build index.html"
}
创建目录结构
index.html
package.json
---src
basicusage.js
导入Snabbdom
方法文档链接
https://github.com/snabbdom/snabbdom
安装Snabbdom
npm install snabbdom@0.7.4
在项目的js
文件夹下的01- basicusage.js
文件中,添加如下代码:
import snabbdom from "snabbdom";
console.log(snabbdom);
以上代码的意思就是导入snabbdom
这个包,然后打印其内容。
项目的启动
npm run dev
这时,开启的端口号为1234
因为在node_modules/snabbdom/snabbdom.js
中没有使用export default导出
修改导入格式
import { h, thunk, init } from "snabbdom";
console.log(h, thunk, init);
基本使用
在01- basicusage.js
文件中编写如下代码
import { h, thunk, init } from "snabbdom";
// init方法返回值为patch函数,patch函数作用是对比两个vndoe的差异并更新到真实的DOM中。init函数的参数是一个数组,数组中的内容是模块,关于模块内容后面还会讲解
let patch = init([]);
//创建虚拟DOM
// 第一个参数:标签+选择器(id选择器或者是类选择器)
// 第二个参数:如果是字符串的话就是标签中的内容
let vnode = h("div#container.cls", "Hello World");
//我们这里需要将创建的虚拟dom,最终要渲染到`index.html`中`app`这个div中,所以这里需要获取一下该div
let app = document.querySelector("#app");
//要想将虚拟DOM渲染到`app`中,需要用到patch函数。
// 我们知道patch函数的作用是对比两个vnode的差异来更新到真实的`DOM`中。
//但是我们目前没有两个虚拟DOM.那么patch方法的第一个参数也可以是真实的DOM.patch方法会将真实的DOM转换成VNode.
// 第二个参数:为VNode
//返回值为VNode
let oldNode = patch(app, vnode);
vnode = h("div", "Hello Vue");
patch(oldNode, vnode);