阅读须知
- 文章参考的preact版本是10.5.13
- 文章会省略大部分逻辑,比如hydrating,context,isSvg等。所以如果有大佬点进来需谨慎。
- 简略版本代码
diffElementNodes概览
- 作用:对参数dom进行各种属性比较赋值 或者 新建dom返回。
- 如果oldVnode上没有dom会根据对应type去新建
- 处理props和children
- 对于文本节点直接修改data从而实现dom的复用修改,nodeType===null
- 非文本节点:对比props,对比子节点
function diffElementNodes(
dom,
newVNode,
oldVNode,
commitQueue,
) {
let oldProps = oldVNode.props
let newProps = newVNode.props
let nodeType = newVNode.type
let i = 0
// 没有dom就去创建节点
// 处理props和children
return dom
}
创建节点
- 没有nodeType就默认创建文本节点,有的就根据类型创建对应节点
// 如果oldVnode上没有dom会根据对应type去新建
if (dom == null) {
if (nodeType === null) {
return document.createTextNode(newProps)
}
dom = document.createElement(
nodeType,
newProps.is && newProps
)
excessDomChildren = null
}
props和children的处理
文本节点
// 在children.js 对比文本节点的不同会先创建新的文本节点的vNode,type===null
// 对于文本节点直接修改data从而实现dom的复用修改
if (nodeType === null) {
if (oldProps !== newProps && dom.data !== newProps) {
dom.data = newProps
}
}
非文本节点
else {
excessDomChildren = excessDomChildren && EMPTY_ARR.slice.call(dom.childNodes)
oldProps = oldVNode.props || EMPTY_OBJ
diffProps(dom, newProps, oldProps, isSvg, isHydrating)
i = newVNode.props.children
diffChildren(
dom,
Array.isArray(i) ? i : [i],
newVNode,
oldVNode,
commitQueue,
dom.firstChild, // dom是oldVNode._dom 旧节点的第一个子节点继续做比较
)
if (excessDomChildren != null) {
for (i = excessDomChildren.length
if (excessDomChildren[i] != null) removeNode(excessDomChildren[i])
}
}
}