组件循环引用依赖问题处理

概述

工程化框架开发项目中,我们会写很多组件,有时候会有如下一个场景: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模块互相引用均有上述问题。

相关推荐
带娃的IT创业者11 分钟前
重新定义前端构建速度:深度解析 SWC 如何用 Rust 颠覆 JavaScript 工具链
前端·javascript·rust·前端构建·swc
happy_0x3f21 分钟前
前端应用的离线暂停更新策略
开发语言·前端·php
你驴我1 小时前
WhatsApp 消息撤回与编辑的幂等性设计实践
java·服务器·前端·后端·python
新中地GIS开发老师1 小时前
零基础WebGIS开发入门 | GeoJSON数据持久化
前端·javascript·gis·webgis·三维gis开发
blns_yxl2 小时前
正则驱动实时表单验证(HTML+CSS+JS+正则)
javascript·css·html
sunywz2 小时前
【c#】 Web Deploy一键发布,IIS部署全流程
开发语言·前端·c#
宁&沉沦2 小时前
Chrome 扩展 Manifest 字段版本支持一览(全量)
前端·后端·编辑器
乖孩子2 小时前
Service Worker + IndexedDB 实践
前端
浮生望2 小时前
BFF架构实战:用Express+SSE为Vue3搭建安全的流式对话中间层
前端
Quz3 小时前
QML 与 JavaScript 交互方式:内联函数、外部文件、信号槽与工作线程
javascript·qt