版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jayhkw/article/details/77867756
关于virtual Dom
一、createElement(): 用 JavaScript对象(虚拟树) 描述 真实DOM对象(真实树)
二、diff(oldNode, newNode) : 对比新旧两个虚拟树的区别,收集差异
三、patch() : 将差异应用到真实DOM树
或者
- Javascript DOM模型树(VTree),类似文档节点树(DOM)
2.DOM模型树转节点树方法(VTree -> DOM)
3.两个DOM模型树的差异算法(diff(VTree, VTree) -> PatchObject)
4.根据差异操作节点方法(patch(DOMNode, PatchObject) -> DOMNode)
关于vTree 与 React的createElement
vtree
{
// tag的名字
tagName: 'p',
// 节点包含属性
properties: {
style: {
color: '#fff'
}
},
// 子节点
children: [],
// 节点变动识别
key: 1
}
React createElement
react.createElement('div', null, [
// 子节点img
react.createElement('img', { src: "avatar.png", class: "profile" }),
// 子节点h3
react.createElement('h3', null, [[user.firstName, user.lastName].join(' ')])
]);
一个简单的react.createElement实现 Create函数
function create(vds, parent) {
// 首先看看是不是数组,如果不是数组统一成数组
!Array.isArray(vds) && (vds = [vds]);
// 如果没有父元素则创建个fragment来当父元素
parent = parent || document.createDocumentFragment();
var node;
// 遍历所有VNode
vds.forEach(function (vd) {
// 如果VNode是文字节点
if (isText(vd)) {
// 创建文字节点
node = document.createTextNode(vd.text);
// 否则是元素
} else {
// 创建元素
node = document.createElement(vd.tag);
}
// 将元素塞入父容器
parent.appendChild(node);
// 看看有没有子VNode,有孩子则处理孩子VNode
vd.children && vd.children.length &&
create(vd.children, node);
// 看看有没有属性,有则处理属性
vd.properties &&
setProps({ style: {} }, vd.properties, node);
});
return parent;
}
DIFF算法
示意图
词汇概念
a. VNode
VNode 虚拟节点,它可以代表一个真实的 dom 节点。通过 createElement 方法能将 VNode 渲染成 dom 节点。
b. VText
VText 虚拟文本节点,代表了一个真实的文本节点。内容中若有 HTML 会被转义。
c. Hooks
Hooks 钩子方法,如给节点注册 ev-click 等事件。
d. Thunk
Thunk 方法允许开发者参与 diff 过程。如对于某节点,能够预先判断状态不会发生改变,则可以通过此方法,在 diff 过程中直接返回旧 VNode 。
e. Widget
Widget 和 Thunk 的作用有点相似,但它参与的是 patch 的过程。它能定制如何渲染成最终的 dom 节点。如要求某个状态只为偶数时,重新渲染等。
f. VPatch
VPatch 权且称之为「补丁对象 」,它描述了对于某个节点的具体操作,比如删除,插入,排序等等。