开发者问题收集

vuejs 递归单文件组件

2018-12-12
3338

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
    }
3个回答

这可能是由于 TreeListTreeNode 组件之间的 循环引用 而发生的。

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')
    }
    ...
}
Husam Elbashir
2018-12-12

使用 Vue 3,您可以使用异步组件:

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

文档:

Motla
2021-09-27

您可以将导入的组件作为数据传递。您甚至可以将它们作为 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
      }
    };
  }
};
Jaredcheeda
2023-10-19