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

vue3 使用defineAsyncComponent与component标签实现动态渲染组件

内容有些啰嗦,内容记载了当时遇到了bug以及解决问题的思路。

业务场景简述:
前端做配置化组件,通过url内的唯一标识,请求后端sql 哪取页面配置信息,前端通过配置信息动态渲染查询表单,导出、表格,toolbar以及动态弹窗;该动态渲染组件的功能,就是渲染的toolbar内的按钮,类型为自定义弹窗,弹窗路径为后端配置数据,前端通过点击该按钮,打开指定路径下的弹窗组件。

之前用的vue2的动态挂载组件,也没见vue3那么麻烦,官网上的例子以及网上的所以例子都是前端知道要导哪些组件,然后程序进入就直接导进来了,只是写了逻辑动态切换。我这个不一样,需要挂载的组件是未知的。所以实现起来有点吃力。

一、基础的动态引入组件:
简单的动态引入的意思是,前端知道要引入哪些组件,将多个组件引入到父组件中,但不渲染它,满足一定条件后,才去在某个位置渲染指定的组件。

<template><custom-modal ref="custom"></custom-modal>
</template>
<script>import {reactive,ref,shallowReactive,onActivated,defineAsyncComponent,} from 'vue';const customModal = defineAsyncComponent(() => import('./modal/CustomModal.vue'));const custom = ref();</script>

以上的例子就是通过vue的defineAsyncComponent实现挂载组件,并赋值给customModal ,模板中可以直接使用<custom-modal>作为标签使用,也可以将它赋值给component中的is属性,is属性执向一个变量,可通过业务逻辑动态,更改该变量的值,就可以实现多个组件进行来回的渲染了

<template>
<component :is="componentKey" ref="custom"></component>
</template>import {reactive,ref,shallowReactive,onActivated,defineAsyncComponent,} from 'vue';const componentKey = ref(null);const components: any = shallowReactive({});const customModal = defineAsyncComponent(() => import('./modal/CustomModal.vue'));componentKey  = customModal

二、复杂的引入:不确定到底引入什么组件,组件的路径由后端返回
将以上代码 添加到项目代码中,并不能实现,虽然引入不报错,但是ref一直为undefined,无法调用动态组件内的open函数。
不断尝试了很多次,得出以下结论

1.起初是在按钮的click函数内去挂载自定义组件并调用ref函数的,ref为undefined。
尝试多次不能实现功能(这里是挂载与调用最合适的位置),
2.接着又在初始化配置数据时(查询后端sql),axios的then函数内挂载组件,然后点击按钮的地方调用ref内的函数,ref依旧为null。
3. 接着在最外层,调用初始化时挂载,也就是生命周期函数体内,测试还是一样的结果。
4. 接着发现带有async函数体内挂载组件,也无法完成。
5.单独写个函数,不加async,函数内挂载组件,然后再生命周期外调用该函数,按钮内调用ref内的方法,成功弹窗。这并不是我想要的,因为路径不是固定的,它要等到后端sql放回结果,才能执行。
总结:上面的多次测试,得出以下结论,
1、不能在组件的事件函数内挂载,
2、不能在axios的then函数体内挂载
3、不能在带有async声明的函数体内挂载
4、不能在vue的生命周期内挂载
5、只能在最外层挂载实现,这时ref才是个对象。

好在天无绝人之路;脑海里有个思路:
页面初始化时将项目里所有的全局挂载view组件扔到一个object内,使用component组件,is:对应object内指定的组件对象,然后通过后端的数据,这时后端就不用给组件路径了,给个组件名,我从object中找到挂载的组件然后将对象给is。
const modules = import.meta.glob('@/views/*/**.vue'); // 获取所有项目路径
mudules为views内所有的vue的相对路径,然后循环它,在循环体内实现挂载,将它存入一个对象内,key为相对路径的项目名称(可以截取以下)。

有了上面的思路,通过反复测试和实现,最终功能实现了。

<template>
<component :is="componentKey" ref="custom"></component>
</template>
<script>import {reactive,ref,shallowReactive,onActivated,defineAsyncComponent,} from 'vue';//声明componentkey,用于告诉component当前挂载什么组件,components为一个对象,存放多个不确定的自定义组件。const componentKey = ref(null);const components: any = shallowReactive({});// 组件挂载const initTableConfig = (gridId, type) => { queryTableConfig({ gridId }).then(({ data }) => {if (type === 'main') {Object.assign(mainConfig, data);tabsKey.value = -1;} else {tabsDetail.value.push(data);tabsKey.value = tabsDetail.value.length - 1;}// 涉及到自定义组件的部分,这里需要提前挂载,在用到时不至于ref为nullXEUtils.objectEach(data.action, (action, key) => {if (action.modalCfg &&action.modalCfg.type === 'CustomModal' &&action.modalCfg.src) {components[action.actionId] = defineAsyncComponent(() => import(`../../../${action.modalCfg.src}`));//注意:这里的路径后端只能返回相对路径,不能使用@/xxx/xxx.vue ,不能使用src/xxx/xxx.vue,只能./xxx.vue或者../../xxx/xxx.vue。由于并不确定组件在什么位置,避免容易出错的原则,我在前端通过../../../的形式将路径回退到src下,后端只需要从src下配置路径即可,不用考虑那么多了。如后端src的值为src/xxx/xxx/xxx.vue 则在前端合成的路径就为../../../src/xx/xxx/xxx.vuecomponentKey.value = components[action.actionId];// 为什么componentKey.vue在这里赋值,在后面点击窗口后又赋值,这里能不能省略。//	答:这里省略的话,到点击按钮触发时会报错,第一次点击会报错,第二次点击不会报错,窗口正常弹出。可能是因为,组件挂载时并没有引入组件,只在使用时才引入,如果上面不提前将挂载好的组件引入进来,后面触发事件触发时引入在调用ref,执行太快,costom就会报错,所以才会点两次才弹窗。}});});};</script>

按钮点击触发事件,确定弹窗要弹出什么组件

		} else if (action.modalCfg.type === 'CustomModal') {// 这里的actionid和组件是对应的,所以在按钮触发后,通过按钮携带的actionid能取到对应的组件。componentKey.value = components[action.actionId];custom.value.init(row);}

经过以上的方式:在任何地方挂载都不会报错,完美解决。
注意:挂载与使用ref不能在同一个方法体内,如果可以的话,页面加载时,执行挂载,需要调用ref时就不会报错。

相关文章:

vue3 使用defineAsyncComponent与component标签实现动态渲染组件

内容有些啰嗦&#xff0c;内容记载了当时遇到了bug以及解决问题的思路。 业务场景简述&#xff1a; 前端做配置化组件&#xff0c;通过url内的唯一标识&#xff0c;请求后端sql 哪取页面配置信息&#xff0c;前端通过配置信息动态渲染查询表单&#xff0c;导出、表格&#xff…...

Linux下 C/C++ NTP网络时间协议详解

NTP&#xff08;Network Time Protocol&#xff0c;网络时间协议&#xff09;是由RFC 1305定义的时间同步协议。它是通过网络在计算机系统之间进行时钟同步的网络协议。NTP 在公共互联网上通常能够保持时间延迟在几十毫秒以内的精度&#xff0c;并在理想条件下&#xff0c;它能…...

Pytest自动化框架-权威教程02-Pytest 使用及调用方法

Pytest 使用及调用方法使用python -m pytest调用pytest2.0版本新增你可以在命令行中通过Python编译器来调用Pytest执行测试:Copypython -m pytest [...]通过python调用会将当前目录也添加到sys.path中,除此之外,这几乎等同于命令行直接调用pytest [...]。可能出现的执行退出cod…...

大数据技术——概述

根据IBM前首席执行官郭士纳的观点&#xff0c;IT领域每隔十五年就会迎来一次重大变革三次信息化浪潮1.存储设备容量不断增加2.CPU处理能力大幅提升3.网络带宽不断增加运营式系统阶段数据库的出现使得数据管理的复杂度大大降低,数据往往伴随着一定的运营活动而产生并记录在数据库…...

java-代理模式

背景 代理模式指的是提供一个代理对象用于访问目标对象,可以很方便的在不修改目标对象的情况下,提供额外的功能,扩展目标对象。 case1:静态代理 约束:代理对象和目标对象要实现相同的接口 优点:不修改目标对象的情况下扩展功能 缺点:必须实现相同的接口,如果接口发生变…...

路由网络的构建与配置

Part.1 ⑴ 需求分析 在构建的局域网中&#xff0c;通过路由器间配置静态路由&#xff0c;实现PC1和PC2主机直接连通&#xff0c;主机网段不能与路由器直接互联网段通信。 ⑵ 环境要求 配置虚拟网卡的计算机&#xff0c;安装华为eNSP模拟软件。 规划拓扑 Part.2 ⑴ 拓扑描述…...

软件测试-接口测试-数据库管理

文章目录 1.数据库介绍2.数据库基本操作2.1安装2.2 操作流程2.3数据准备2.4数据的基本操作2.4.1 连接数据库并查询数据库版本2.4.2 连接数据库执行数据库查询操作2.4.3 连接数据库执行数据库插入操作2.4.4 连接数据库执行数据库更新操作3.数据库事务操作3.1 案例:数据不一致性…...

【华为OD机试 】天然蓄水库(C++ Java JavaScript Python)

文章目录 题目描述输入描述输出描述备注用例题目解析C++JavaScriptJavaPython题目描述 公元2919年,人类终于发现了一颗宜居星球——X星。 现想在X星一片连绵起伏的山脉间建一个天热蓄水库,如何选取水库边界,使蓄水量最大? 要求: 山脉用正整数数组s表示,每个元素代表山脉…...

普元EOS中导出excl页面下载

起因 需要做一个筛选功能的导出表格 解决办法 这个垃圾eos我是真受不了,sb玩意的缺点三天三夜也说不完 后边就没法整response的这些个东西,可真是够愁人的 在网上搜了搜 在普元的帮助文档里也看了看 普元提供的像是老太太的裹脚布一般又臭又长 参照这个可以看一下...

内存的管理

取指令——译码——执行——返存 计组课我们学过cpu真正读指令并非是从内存中读入&#xff0c;而是从cache读和存&#xff0c;再由cache进行取指或返存&#xff0c;因为cpu指令周期比内存周期速度快很多&#xff0c;cpu若要取指或返存都需要等待内存完成他的动作才可以进行下一…...

OpenFeign 切换HttpClient遇到的问题

背景 OpenFeign支持三种Http请求方式&#xff0c;默认情况下通过jdk中的HttpURLConnection向下游服务发起http请求&#xff08;详见下图&#xff0c;源码详见feign.Client.Default&#xff09;&#xff0c; 默认的Client 采用 HttpURLConnection&#xff0c; 这种是无法复用的…...

流计算框架storm概览

Attention: supervison 和 nimbus的状态都实时保存在zookeeper集群中和本地. Enchance, this means you can kill -9 Nimbus or the Supervisors and theyll start back up as nothing happened. Topologies 1. storm jar all-my-code.jar org.apache.storm.MyTopology a…...

如何使用Coercer强制Windows Server认证任意主机

关于Coercer Coercer是一款功能强大的Python脚本&#xff0c;该工具可以通过九种不同的方法来强制让一台Windows Server认证任意主机。 功能介绍 1、自动检测远程设备的开放SMP管道&#xff1b; 2、一一调用存在安全漏洞的RPC功能来强制一台Windows Server认证任意主机&#…...

【小程序】已有公众号认证,一步一步申请小程序(图文)

一、登陆公众号后台&#xff0c;找到左侧广告与服务&#xff0c;小程序管理&#xff0c;开通 二、选择快速注册认证小程序 三、快速创建 四、选择微信认证资质&#xff08;复用&#xff09;&#xff0c;这样不用再付认证费了 五、需要一个新的邮箱&#xff0c;这点挺让人无语&a…...

Redis学习笔记:缓存运用常见问题

这是本人学习的总结&#xff0c;主要学习资料如下 马士兵教育 目录1、数据一致性的问题1.1、新增数据一致性的问题1.2、修改/删除一致性问题1.2.1、操作分析1.2.1、总结和再深入2、缓存穿透&#xff0c;缓存击穿和缓存雪崩2.1、缓存穿透&#xff08;查不到&#xff09;2.1.1、…...

使用python 脚本挑出coco 数据集中的某一类数据

文章大纲 简介代码样例制作一个走路玩手机数据集简介 MS COCO的全称是Microsoft Common Objects in Context,起源于微软于2014年出资标注的Microsoft COCO数据集,与ImageNet竞赛一样,被视为是计算机视觉领域最受关注和最权威的比赛之一。 COCO数据集是一个大型的、丰富的物…...

Python虚拟环境(pipenv、venv、conda一网打尽)[通俗易懂]

一、什么是虚拟环境 1. 什么是Python环境 要搞清楚什么是虚拟环境&#xff0c;首先要清楚Python的环境指的是什么。当我们在执行python test.py时&#xff0c;思考如下问题&#xff1a; python哪里来&#xff1f;这个主要归功于配置的系统环境变量PATH&#xff0c;当我们在命…...

Android Kotlin实战之高阶使用泛型扩展协程懒加载详解

前言&#xff1a; 通过前面几篇文章&#xff0c;我们已基本掌握kotlin的基本写法与使用&#xff0c;但是在开发过程中&#xff0c;以及一些开源的API还是会出现大家模式的高阶玩法以及问题&#xff0c;如何避免&#xff0c;接下来讲解针对原来的文章进行一些扩展&#xff0c;解…...

数字映射:数字孪生技术的应用场景及作用

对于许多行业来说&#xff0c;数字孪生技术是未来。数字孪生定义数字孪生不仅仅是某物的副本或克隆&#xff0c;它是对象或系统的动态实时表示。数字孪生是一种虚拟模型&#xff0c;旨在准确反映物理对象。是物理对象、流程、服务或环境的数字表示&#xff0c;其行为和外观与现…...

配置二层远程端口镜像案例

实验拓扑&#xff1a; 实验需求&#xff1a; 如图1所示&#xff0c;某公司行政部通过SwitchA与外部Internet通信&#xff0c;监控设备Server通过SwitchB与SwitchA相连。 现在希望Server能够远程对行政部访问Internet的流量进行监控。 操作步骤&#xff1a; 配置观察端口 # 在…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...