一、虚拟DOM
(1)概念
虚拟DOM(Virtual DOM)-> Vue React核心
通过JS去模拟DOM结构
比如把表单里的abc改成dbc,用JQuery的话就会先去除abc,再改成dbc,这样就比较消耗性能
如果用虚拟DOM的话,就只需要修改更改的内容就可以了,这样性能相对的提升了
(2)snabbdom
snabbdom是一个虚拟DOM库
h函数: 帮助生成一个虚拟的dom节点
// 第一个参数是类名、第二个参数是属性,第三个参数是子节点
var vnode = h("ul#list", {}, [
h("li.list-item", {}, "first item"),
h("li.list-item", {}, "second item")
])
对应的虚拟dom结构:
{
tag: 'ul',
attrs: {
id: 'list'
},
children: [
{
tag:'li',
attrs: { className: 'list-item' },
children: ['first item']
},
{
tag: 'li',
attrs: { className: 'list-item' },
children: ['second item']
}
]
}
patch函数:
如果第一个参数是node,就会被第二个参数的vnode替换
如果两个都是vnode会进行对比,更新或增加相对应的vnode
patch(container, vnode);
patch(vnode, newVnode);
(3)diff算法
比较两个文件之间的不同
snabbdom就是利用diff算法找出dom里面需要更新的节点有哪些
示例1
用JQuery做点击改变按钮修改container里面的内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="container"></div>
<button id="changeBtn">改变</button>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
var data = [
{
name: "张三",
age: 20,
job: "司机"
},
{
name: "李四",
age: 30,
job: "银行职员"
},
{
name: "王五",
age: 40,
job: "公司经理"
}
]
// 渲染函数
function render(data) {
var $container = $('#container');
// 清空
$container.html('');
// 拼接table
var $table = $("<table>");
$table.append($("<tr><td>姓名</td><td>年龄</td><td>职位</td><tr>"));
data.forEach(function (item) {
$table.append($("<tr><td>" + item.name + "</td><td>" + item.age + "</td><td>" + item.job + "</td><tr>"));
});
// 渲染到页面
$container.append($table);
}
$('#changeBtn').click(function () {
data[0].name = "赵六";
data[1].job = "飞行员";
// 重新渲染
render(data);
});
// 初次渲染
render(data);
</script>
</body>
</html>
点击发现整个container,及table都在闪烁,说明对他们都进行了修改
示例2
用虚拟dom来做点击改变修改container里面的内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="container">
</div>
<button id="changeBtn">改变</button>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/snabbdom/0.7.4/snabbdom.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/snabbdom/0.7.4/snabbdom-class.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/snabbdom/0.7.4/snabbdom-props.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/snabbdom/0.7.4/snabbdom-style.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/snabbdom/0.7.4/snabbdom-eventlisteners.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/snabbdom/0.7.4/h.min.js"></script>
<script>
var container = document.getElementById('container'),
changeBtn = document.getElementById('changeBtn');
var snabbdom = window.snabbdom;
// 定义patch函数
var patch = snabbdom.init([
snabbdom_class,
snabbdom_props,
snabbdom_style,
snabbdom_eventlisteners
]);
// 定义h函数
var h = snabbdom.h;
// 生成vnode
var vnode = h("ul#list", {}, [
h("li.list-item", {}, "first item"),
h("li.list-item", {}, "second item")
]);
patch(container, vnode);
changeBtn.addEventListener("click", function () {
// 生成新的vnode
var newVnode = h("ul#list", {}, [
h("li.list-item", {}, "第一个item"),
h("li.list-item", {}, "second item"),
h("li.list-item", {}, "third item")
]);
patch(vnode, newVnode);
// 已经存在就不会替换,只会替换没有的或有变化的
});
</script>
</body>
</html>
发现只有修改的内容在闪烁,也就是只修改了更改过的内容