11. 实现 Text 和 Fragment
11. 实现 Text 和 Fragment
除了元素虚拟节点之外,Vue3 中还有很多其他类型的虚拟节点,这里我们先来说下 Text 和 Fragment 的实现
export const Text = Symbol('Text');
export const Fragment = Symbol('Fragment');
1.文本类型
render(h(Text, 'erxiao handsome'), document.getElementById('app'));
const patch = (n1, n2, container, anchor?) => {
// 初始化和diff算法都在这里喲
if (n1 == n2) {
return;
}
if (n1 && !isSameVNodeType(n1, n2)) {
// 有n1 是n1和n2不是同一个节点
unmount(n1);
n1 = null;
}
const { type, shapeFlag } = n2;
switch (type) {
case Text:
processText(n1, n2, container); // 处理文本
break;
case Fragment:
processFragment(n1, n2, container); // 处理fragment
break;
default:
if (shapeFlag & ShapeFlags.ELEMENT) {
processElement(n1, n2, container, anchor); // 之前处理元素的逻辑
}
}
};
const processText = (n1, n2, container) => {
if (n1 == null) {
hostInsert((n2.el = hostCreateText(n2.children)), container);
} else {
const el = (n2.el = n1.el);
if (n2.children !== n1.children) {
hostSetText(el, n2.children);
}
}
};
2.Fragment 类型
render(
h(Fragment, [h(Text, 'hello'), h(Text, 'erxiao')]),
document.getElementById('app')
);
const processFragment = (n1, n2, container) => {
if (n1 == null) {
mountChildren(n2.children, container);
} else {
patchChildren(n1, n2, container);
}
};
为了让 Vue3 支持多根节点模板,Vue.js 提供 Fragment 来实现,核心就是一个无意义的标签包裹多个节点。
同时这里要处理下卸载的逻辑,如果是 fragment 则删除子元素
const unmount = (vnode) => {
if (vnode.type === Fragment) {
return unmountChildren(vnode.children);
}
hostRemove(vnode.el);
};