vuejs 递归单文件组件
Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
我有一个侧边栏,其中包含一个 TreeList,该 TreeList 包含 TreeNode,每个 TreeNode 都包含一个 TreeList。
我读过很多关于其他人遇到此问题的文章。我尝试过一些解决方案,例如为组件指定 kebab 大小写名称。我读到过这是命名空间的问题,我同意,因为我有一个使用单个文件中所有组件的示例。当组件位于单独的文件中时,使用 vue CLI 重新加载我的脚本时会发生上述错误。偶尔,在保存文件时,没有任何解释,错误就会消失,递归再次起作用。
然后,当它正常工作时,单击子节点时会出现错误。
Cannot read property 'length' of undefined at simpleNormalizeChildren
这与 vue CLI 服务有关吗? 我愿意在全局命名空间中声明这些内容,但我不确定它具体如何工作。
import TreeList from './TreeList.vue'
export default {
name: 'tree-node',
components: {
'tree-list': TreeList
},
...
import TreeNode from './TreeNode.vue'
export default {
name: 'tree-list',
components: {
'tree-node': TreeNode
}
...
import TreeList from './TreeList.vue'
import TreeNode from './TreeNode.vue'
export default {
name: 'Sidebar',
components: {
TreeList,
TreeNode
}
这可能是由于
TreeList
和
TreeNode
组件之间的
循环引用
而发生的。
When you look closely, you’ll see that these components will actually be each other’s descendent and ancestor in the render tree - a paradox!
要解决此悖论,您可以使用
Vue.component
全局注册您的组件,也可以将某个组件的导入推迟到以后的时间点(通过将导入移至
beforeCreate
挂钩或使用
异步组件
,如示例
这里
)..
TreeList.vue
export default {
name: 'tree-list',
components: {
'tree-node': () => import('./TreeNode.vue')
}
...
}
使用 Vue 3,您可以使用异步组件:
export default {
name: 'tree-list',
components: {
'tree-node': defineAsyncComponent(() => import('./TreeNode.vue'))
}
}
文档:
您可以将导入的组件作为数据传递。您甚至可以将它们作为 prop 传递,也可以将它们作为传递给 prop 的对象传递。
<!-- TheParent.vue -->
<template>
<RecursiveComponent
:nodes="nodes"
:component="RecursiveComponent"
/>
</template>
<script>
import RecursiveComponent from '@/components/RecursiveComponent.vue';
export default {
name: 'TheParent',
components: {
RecursiveComponent
},
data: function () {
return {
nodes: {
a: {
b: {
c: 22
}
},
d: 33
}
};
},
computed: {
RecursiveComponent: function () {
return RecursiveComponent;
}
}
};
</script>
<!-- RecursiveComponent.vue -->
<template>
<ul>
<li v-for="(value, key) in nodes">
<strong>{{ key }}: </strong>
<template v-if="typeof(value) !== 'object'">
{{ nodes[key] }}
</template>
<component
v-else
:is="component"
:nodes="value"
:component="component"
/>
</li>
</ul>
</template>
<script>
export default {
name: 'RecursiveComponent',
props: {
nodes: {
type: Object,
required: true
},
component: {
type: Object,
required: true
}
}
};
</script>
注意:
- 这在本地以及在为生产构建项目时都可以正常工作,但某些在线编辑器(如 CodeSandbox)在实时更新递归代码时会遇到困难。
-
组件存储在
computed
部分中,以便模板可以访问。您可以将其存储在data
中,但 Vue 会警告说它将变为反应式(这不是很好)。如果使用 此插件 ,您也可以将其放在constants
部分。
import RecursiveComponent from '@/components/RecursiveComponent.vue';
export default {
name: 'TheParent',
components: {
RecursiveComponent
},
constants: {
RecursiveComponent
},
data: function () {
return {
nodes: {
a: {
b: {
c: 22
}
},
d: 33
}
};
}
};