5
votes

Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.

I have a Sidebar that contains a TreeList that contains TreeNodes that each contain a TreeList.

I have read plenty about other people having problems with this. I have tried solutions such as specifying kebab case names for the components. I have read about this being a problem with namespace and I agree, because I have an example working with all components in a single file. When the components are in separate files the above error occurs when reloading my script using vue CLI. Occasionally and without explanation when saving my file the error goes away and the recursion works again.

Then when it works correctly there is an error when clicking on child nodes.

Cannot read property 'length' of undefined at simpleNormalizeChildren

Is it something do with vue CLI serve? I am open to declaring these things in the global namespace except I'm not sure how that would work exactly.

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
    }
2

2 Answers

9
votes

This is probably happening because of the circular referencing between your TreeList and TreeNode components ..

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!

To resolve this paradox you can either register your components globally using Vue.component, or you can defer the import of one of your components to a later point (by moving your import to the beforeCreate hook or using async components as demonstrated here) ..

TreeList.vue

export default {
    name: 'tree-list',
    components: {
        'tree-node': () => import('./TreeNode.vue')
    }
    ...
}
0
votes

With Vue 3, you can use Async Components:

export default {
  name: 'tree-list',
  components: {
    'tree-node': defineAsyncComponent(() => import('./TreeNode.vue'))
  }
}

Documentation: