当前位置: 首页 > 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 的缓存机制避免重复请求。
  • 实际开发中应根据组件大小、使用频率选择合适的加载方式。
http://www.xdnf.cn/news/482887.html

相关文章:

  • 简单入门RabbitMQ
  • Centos7 中 Docker运行配置Apache
  • 基于Scrapy-Redis的分布式景点数据爬取与热力图生成
  • skywalking使用教程
  • LLaMA-Factory:环境准备
  • 大语言模型核心技术解析:从训练到部署的全链路实践
  • Python web 开发 Flask HTTP 服务
  • leetcode 2901. 最长相邻不相等子序列 II 中等
  • 测试工程师如何学会Kubernetes(k8s)容器知识
  • 05-SpringBoot
  • 链表的中间结点数据结构oj题(力扣876)
  • BM25 算法与关键词提取在向量数据库中的实践优化
  • tomcat一闪而过,按任意键继续以及控制台中文乱码问题
  • 基于javaweb的SSM驾校管理系统设计与实现(源码+文档+部署讲解)
  • 遥感图像非法采矿矿区识别分割数据集labelme格式1818张3类别
  • R语言如何解决导出pdf中文不显示的问题
  • 苹果新一代车载系统CarPlay Ultra来袭,全屏接管+ChatGPT助力,智能驾驶要“起飞”
  • 钉钉报销与金蝶付款单系统对接技术揭秘
  • ACM模式用Scanner和System.out超时的解决方案和原理
  • 锐捷交换机STP环路日志信息解读
  • NLG的可解释性困局:可视化工具Captum在生成模型中的应用
  • 【学习心得】Jupyter 如何在conda的base环境中其他虚拟环境内核
  • Spring Boot三层架构设计模式
  • 风控贷中策略笔记
  • CSS:颜色的三种表示方式
  • 汽车装配又又又升级,ethernetip转profinet进阶跃迁指南
  • mongodb用systemctl启动code=killed, signal=ABRT
  • 关于 Web安全:1. Web 安全基础知识
  • 全球泳装与沙滩装市场深度洞察:从功能性需求到可持续时尚的蜕变(2025-2031)
  • Elasticsearch-kibana索引操作