递归组件我们用的比较少,但是在Tree、Menu这类组件中会被用到。
组件通过组件名称引用它自己,这种情况就是递归组件。
An SFC can implicitly refer to itself via its filename.
<template>
<li>
<div> {{ model.name }}</div>
<ul v-show="isOpen" v-if="isFolder">
<!-- 注意这里:组件递归渲染了它自己 -->
<TreeItem
class="item"
v-for="model in model.children"
:model="model">
</TreeItem>
</ul>
</li>
<script>
export default {
name: 'TreeItem',
// ...
}
</script>
- 下定义
- 使用场景
- 使用细节
- 原理阐述
- 如果某个组件通过组件名称引用它自己,这种情况就是递归组件。
- 实际开发中类似Tree、Menu这类组件,它们的节点往往包含子节点,子节点结构和父节点往往是相同的。这类组件的数据往往也是树形结构,这种都是使用递归组件的典型场景。
- 使用递归组件时,由于我们并未也不能在组件内部导入它自己,所以设置组件
name
属性,用来查找组件定义,如果使用SFC,则可以通过SFC文件名推断。组件内部通常也要有递归结束条件,比如model.children这样的判断。 - 查看生成渲染函数可知,递归组件查找时会传递一个布尔值给
resolveComponent
,这样实际获取的组件就是当前组件本身。
递归组件编译结果中,获取组件时会传递一个标识符 _resolveComponent("Comp", true)
const _component_Comp = _resolveComponent("Comp", true)
就是在传递maybeSelfReference
export function resolveComponent(
name: string,
maybeSelfReference?: boolean
): ConcreteComponent | string {
return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name
}
resolveAsset中最终返回的是组件自身:
if (!res && maybeSelfReference) {
// fallback to implicit self-reference
return Component
}
https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/helpers/resolveAssets.ts#L22-L23