概述
工程化框架开发项目中,我们会写很多组件,有时候会有如下一个场景:A组件包含B组件,B组件又依赖A组件,形成了循环引用的问题,这样的组件最好在渲染的时候会导致渲染报错。
示例
有如下两个组件,互相引用依赖

ProductInfo.vue组件
js
<template>
<Products v-for="item in data" :data="item"></Products>
</template>
<script>
import { defineComponent } from "vue";
import Products from "./Products.vue";
console.log("Products--", Products);
export default defineComponent({
name: "ProductInfo",
components: { Products },
props: {
data: {
type: Array,
required: true,
},
},
});
</script>
Products.vue组件
js
<template>
<div class="products">
<div @click="handleAddSub">
name :
{{ data.name }}
</div>
<div>
price :
{{ data.price }}
</div>
<div>
desc :
{{ data.desc }}
</div>
<h2>relateProduct:</h2>
<ProductInfo :data="dataList"></ProductInfo>
</div>
</template>
<script>
import ProductInfo from "./ProductInfo.vue";
import { ref, defineComponent } from "vue";
console.log("ProductInfo", ProductInfo);
export default defineComponent({
name: "Products",
components: {
ProductInfo,
},
props: {
data: {
type: Object,
required: true,
},
},
setup(props) {
const dataList = ref([]);
const handleAddSub = () => {
dataList.value.push({
name: props.data.name + "test",
price: 999,
desc: "i am test",
});
console.log("dataList", dataList);
};
return {
handleAddSub,
dataList,
};
},
});
</script>
app.vue使用
js
<script setup lang="ts">
import ProductInfo from "@/components/product/ProductInfo.vue";
const dataList = [
{ name: "apple", price: 100, desc: "i am apple" },
{ name: "banana", price: 200, desc: "i am banana" },
{ name: "orange", price: 300, desc: "i am orange" },
];
</script>
<template>
<ProductInfo :data = 'dataList'></ProductInfo>
</template>
问题
Products.vue中这里输出组件提示报错页面无法渲染


原因
上面的原因就在于两个组件(模块互相引用),ProductInfo组件开始的时候通过如下导入了Products组件
js
import Products from "./Products.vue";
而Products组件中导入了Products组件,在导入代码进入Products组件的时候,由于ProductInfo组件还没执行后面的export default defineComponent({}),因此无法找到,提示报错
js
import ProductInfo from "./ProductInfo.vue";
解决方案
方案1:全局注册
直接将两个组件全局注册,然后使用
js
//main.js
import ProductInfo from "./ProductInfo.vue";
import Products from "./Products.vue";
app.component(ProductInfo)
app.component(Products)
方案2:异步组件
在运行时候,加载组件,改造Products.vue组件如下,通过异步组件注册动态导入组件
js
<template>
<div class="products">
<div @click="handleAddSub">
name :
{{ data.name }}
</div>
<div>
price :
{{ data.price }}
</div>
<div>
desc :
{{ data.desc }}
</div>
<h2>relateProduct:</h2>
<ProductInfo :data="dataList"></ProductInfo>
</div>
</template>
<script>
// import ProductInfo from "./ProductInfo.vue";
import { ref, defineComponent, defineAsyncComponent } from "vue";
// console.log("ProductInfo", ProductInfo);
export default defineComponent({
name: "Products",
components: {
ProductInfo: defineAsyncComponent(() => import("./ProductInfo.vue")),
},
props: {
data: {
type: Object,
required: true,
},
},
setup(props) {
const dataList = ref([]);
const handleAddSub = () => {
dataList.value.push({
name: props.data.name + "test",
price: 999,
desc: "i am test",
});
console.log("dataList", dataList);
};
return {
handleAddSub,
dataList,
};
},
});
</script>
总结
上面的问题其实不单单是vue组件导入会出现的问题,只要是模块,js模块互相引用均有上述问题。