更新Element
更新element节点,主要是更新props和子节点,内部还涉及到动态patch更新。
const patchElement = (
n1,
n2,
parentComponent,
parentSuspense,
isSVG,
optimized
) => {
const el = (n2.el = n1.el)
let { patchFlag, dynamicChildren, dirs } = n2
patchFlag |= n1.patchFlag & 16 /* FULL_PROPS */
const oldProps = n1.props || EMPTY_OBJ
const newProps = n2.props || EMPTY_OBJ
if (patchFlag > 0) {
if (patchFlag & 16 /* FULL_PROPS */) {
// 更新props
patchProps(
el,
n2,
oldProps,
newProps,
parentComponent,
parentSuspense,
isSVG
)
} else {
// class
if (patchFlag & 2 /* CLASS */) {
if (oldProps.class !== newProps.class) {
// 更新class
hostPatchProp(el, 'class', null, newProps.class, isSVG)
}
}
// style
if (patchFlag & 4 /* STYLE */) {
hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG)
}
// props
if (patchFlag & 8 /* PROPS */) {
const propsToUpdate = n2.dynamicProps
/**
* propsToUpdate是 onClick | onUpdate:modelValue 这些。
* 示例:<polygon :points="points"></polygon> propsToUpdate === ["points"]
*/
for (let i = 0; i < propsToUpdate.length; i++) {
const key = propsToUpdate[i]
const prev = oldProps[key]
const next = newProps[key]
// 这里的next可能是 string number function object boolean
// 比较不同就更新
if (
next !== prev ||
(hostForcePatchProp && hostForcePatchProp(el, key))
) {
hostPatchProp(
el,
key,
prev,
next,
isSVG,
n1.children,
parentComponent,
parentSuspense,
unmountChildren
)
}
}
}
}
// text
if (patchFlag & 1 /* TEXT */) {
if (n1.children !== n2.children) {
hostSetElementText(el, n2.children)
}
}
}
else if (!optimized && dynamicChildren == null) {
// unoptimized, full diff
patchProps(
el,
n2,
oldProps,
newProps,
parentComponent,
parentSuspense,
isSVG
)
}
// full diff
patchChildren(
n1,
n2,
el,
null,
parentComponent,
parentSuspense,
areChildrenSVG
)
}
总结
主要做了以下几件事情:
- 更新 props
- 更新 class
- 更新 style
- 更新 text
- 更新子节点
patchChildren