当前位置: 首页 > news >正文

Vue3项目,子组件默认加载了两次,使用 defineAsyncComponent 引入组件后只加载一次

文章目录

    • 一、场景描述
    • 二、组件为什么会加载两次?
    • 三、使用 defineAsyncComponent 后为何只加载一次?
    • 四、总结对比

在 Vue 3 开发中,可能会遇到这样的问题:某个子组件在页面加载时“看起来”被创建了两次。多少有点让人疑惑,也可能影响性能和逻辑的正确性。

一、场景描述

子组件使用方式,示例代码:

// template
<Childv-if="!detailLoading"ref="childRef"v-model:info="info"
/>// script
import Child from './components/Child.vue';// 在请求详情接口前设置 detailLoading.value = true;接口完成后,在 finally 中设置 detailLoading.value = false
const detailLoading = ref(true);
const getModelDetail = async () => {detailLoading.value = true;try {const res = await xxx;info.value = res;} finally {detailLoading.value = false;}
};

结果:Child 组件被加载了 两次

二、组件为什么会加载两次?

这个问题的核心在于 Vue 的响应式系统和组件生命周期行为,尤其是与 v-if、ref 和组件引入方式有关。

1. v-if 控制组件渲染时机

因为我们使用了 v-if=“!detailLoading” 来控制 < Child > 是否渲染:

<Child v-if="!detailLoading" />

也就是说:

  • 初始时 detailLoading 是 true,所以组件不会渲染。
  • 请求完成后设置 detailLoading = false,触发组件首次渲染。
  • 如果中间状态变化导致 detailLoading 再次变为 true,再变回 false,组件就会再次重新创建。
  • 所以如果我们在代码中不小心多次修改了 detailLoading 的值,或者初始值处理不当,组件就会被创建多次。

2. import 引入组件是同步的

import Child from './components/Child.vue';

这是标准的 ES Module 导入方式,模块在应用启动时就会被加载并执行一次。但注意:导入本身只执行一次,不代表组件实例只创建一次。

每次 v-if 变为 true,Vue 都会重新创建一个新的组件实例。因此:

组件加载次数 = v-if 从 false 变为 true 的次数

三、使用 defineAsyncComponent 后为何只加载一次?

更改引入组件的方式:

const Child = defineAsyncComponent(() =>import('./components/Child.vue')
);

此时发现组件只加载了一次。

原因分析

  1. defineAsyncComponent是懒加载机制
  • 它会在组件第一次需要渲染时才去异步加载组件文件。
  • 加载完成后,组件会被缓存,后续再次渲染时不会再发起新的网络请求。
  1. Vue 内部做了缓存优化
  • 当使用 defineAsyncComponent 包裹动态导入时,Vue 会自动缓存这个异步组件的结果。即使你多次切换 v-if 的值,它也不会重复加载组件文件。

也就是说:

虽然组件实例可能会被销毁重建(由 v-if 控制),但组件文件只加载一次。

四、总结对比

特性import 直接引入defineAsyncComponent + import()
组件文件加载方式同步加载,初始化时即加载异步加载,按需加载
文件是否重复加载不会(模块单例)不会(内部缓存)
组件实例是否重复创建是(由 v-if 控制)是(由 v-if 控制)
适合场景小型组件或首屏必须使用的组件大型组件、非首屏组件、懒加载优化

总结:

  • 使用 import 引入的组件只会加载一次模块,但实例可能被多次创建。
  • 使用 defineAsyncComponent 可以延迟加载组件,并利用 Vue 的缓存机制避免重复请求。
  • 实际开发中应根据组件大小、使用频率选择合适的加载方式。

相关文章:

  • InfluxDB 2.7 连续查询实战指南:Task 替代方案详解
  • 几个正整数常用的位运算操作
  • [特殊字符][特殊字符]知识库PHP版 | ChatMoneyAI宝塔面板Docker多部署
  • JMeter 教程:编写 GET 请求脚本访问百度首页
  • 描述性统计图表
  • Python-homework
  • 前端面经 8 JS中的this 手写call apply bind方法
  • Go语言爬虫系列教程 实战项目JS逆向实现CSDN文章导出教程
  • CSS- 2.1 实战之图文混排、表格、表单
  • 搭建运行若依微服务版本ruoyi-cloud最新教程
  • 实变函数 第二章 点集
  • STM32外设AD-轮询法读取模板
  • 【简单模拟实现list】
  • 腾讯云MCP数据智能处理:简化数据探索与分析的全流程指南
  • 利用腾讯云MCP提升跨平台协作效率的实践与探索
  • 水库雨水情测报与安全监测系统解决方案
  • [模型部署] 1. 模型导出
  • yocto5.2开发任务手册-7 升级配方
  • PT2031S单触控单输出触摸IC
  • pojo层、dao层、service层、controller层的作用
  • 大陆非遗项目打铁花、英歌舞将在台演出
  • “大型翻车现场”科技满满,黄骅打造现代化港口和沿海新城典范
  • 手机表面细菌菌落总数可能比马桶高10倍,医生详解如何洗手
  • 曾犯强奸罪教师出狱后办教培机构?柳州鱼峰区教育局回应
  • 现场丨在胡适施蛰存等手札与文献间,再读百年光华
  • 巴菲特谈卸任CEO:开始偶尔失去平衡,但仍然保持敏锐的头脑,仍打算继续工作