这题现在有些落伍,vue3
已经不用一个根了。因此这题目很有说头!
vue2直接报错,test-v2.html
new Vue({
components: {
comp: {
template: `
<div>root1</div>
<div>root2</div>
`
}
}
}).$mount('#app')
vue3中没有问题,test-v3.html
Vue.createApp({
components: {
comp: {
template: `
<div>root1</div>
<div>root2</div>
`
}
}
}).mount('#app')
- 给一条自己的结论
- 解释为什么会这样
vue3
解决方法原理
vue2
中组件确实只能有一个根,但vue3
中组件已经可以多根节点了。- 之所以需要这样是因为
vdom
是一颗单根树形结构,patch
方法在遍历的时候从根节点开始遍历,它要求只有一个根节点。组件也会转换为一个vdom
,自然应该满足这个要求。 vue3
中之所以可以写多个根节点,是因为引入了Fragment
的概念,这是一个抽象的节点,如果发现组件是多根的,就创建一个Fragment节点,把多个根节点作为它的children。将来patch的时候,如果发现是一个Fragment节点,则直接遍历children创建或更新。
-
patch方法接收单根vdom:
https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L354-L355
// 直接获取type等,没有考虑数组的可能性 const { type, ref, shapeFlag } = n2
-
patch方法对Fragment的处理:
https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L1091-L1092
// a fragment can only have array children // since they are either generated by the compiler, or implicitly created // from arrays. mountChildren(n2.children as VNodeArrayChildren, container, ...)