新虚拟DOM与旧的虚拟DOM进行
diff
精细化比较,算出如何最小量更新
,最后反应到真实DOM上;
- key很重要,key是这个节点的唯一标识,告诉diff算法,在更改前后它们是同一节点;
- 只有是同一虚拟节点,才会进行精细化比较,否则就会暴力拆除旧的,插入新的。
- 那么问题来了,什么才叫同一虚拟节点,答:选择器相同且key相同。
- diff算法只会进行同层比较,不会进行跨层比较,即使是同一虚拟节点,但是跨层了,对不起,diff也不会进行比较,只会暴力拆除旧的,插入新的;
一个虚拟节点,包含哪些属性:
{
children:undefined, //包含的子节点 undefined说明没有字节点
data:{}, //该节点所包含的属性
elm:undefined, //对应的真实DOM节点名字 undefined说明没有上树,浏览器还不会显示
key:undefined, //真实DOM上的唯一值key undefined说明没有key
sel:"div", //当前dom 的名字
text:'我是一个盒子' //该节点内的文本信息
}
里面有几个重要的函数:
着重看h函数和patch函数
import { init } form 'snabbdom/init';
import { classModule } form 'snabbdom/module/class';
import { propsModule } form 'snabbdom/module/props';
import { styleModule } form 'snabbdom/module/style';
import { eventListenersModule } form 'snabbdom/module/eventlistenersModulers';
import { h } from 'ansbbdom/h';
// 创建patch 函数 patch 函数是diff 算法核心函数
const patch = init([classModule, propsModule, styleModule, eventListenersModule]);
// 创建虚拟节点
//h函数中的参数:h('标签名','属性','内部的值')
const vnode1 = h{'a', {
props: {
href: 'https://baidu.com';
target: '_blank'
}
}, '百度'}
// patch 函数接受两个参数: 第一个参数(dom节点); 第二个参数: (vnode) 虚拟节点
// 让虚拟节点上树
// 首先创建container
const container = document.getElementById('container');
patch(container, vnode1)
h 函数可以嵌套使用, 从而得到虚拟DOM树
//1: 比如这样嵌套函数
h('ul',{}, [
h('li', {}, '牛奶'), // h 函数用于创建vnode 节点
h('li', {}, '咖啡'),
h('li', {}, '可乐'),
])
// 2: 得到这样的虚拟DOM 树
{
"sel": "ul",
"data": {},
"children": {
{ se:"li", text: "牛奶" },
{ se:"li", text: "咖啡" },
{ se:"li", text: "可乐" }
}
}
// h 函数
const vnode3 = h('ul', [
h('li', {}, '苹果'),
h('li', '西瓜'),
h('li', [
h('div', [
h('p', '11111'),
h('p', '22222'),
])
])
h('li', h('p', '山楂'))
])
为什么要加key
如果
不加key
的话,在前面加E节点时,会重新打乱,重新渲染
。如果加了key
,diff就会直接找到key='E'的节点,而其他的节点不会动
,从而完成最小量更新.