Vue 批量注册组件实现动态组件技巧

news2024/11/18 4:34:53

介绍

Vue 动态组件的应用场景很多,可应用于动态页签,动态路由等场景,其核心原理是批量注册。在Vue2和Vue3中实现原理相同,只是语法略有差异。

Vue2 实现

基于 webpack

require.context() 是webpack提供的一个自动导入的API
参数1:加载的文件目录
参数2:是否加载子目录
参数3:正则,匹配文件
返回值:导入函数 fn
使用require提供的函数context加载某一个目录下所有的.vue后缀的文件,他的返回值是一个对象,对象里面有一个属keys(), 可以获取所有的文件路径,我们可以遍历importFn.keys(),最后在遍历中使用

首先先描述下应用场景,比如我想在父容器遍历组件集合,根据组件类型(字符串)来首先动态加载组件,如下图:
在这里插入图片描述
如果要是按正常一个个注册的话,也是可以的,就是代码冗余多,不够优雅,所以需要一个方法来实现,这个方法就放到一个JS里去,然后把该index.js直接丢到widget-attr文件夹里.

//index.js
const requireComponent = require.context('./', false, /\w+\.vue$/)
let comps = {}
requireComponent.keys().map(fileName => {
  let comp = requireComponent(fileName).default;
  comps[comp.name] = comp
})
export default comps;

然后在页面引用,如下图:
在这里插入图片描述
好了,到这里简简单单就实现了,我现在整个项目需要这样批量注册的场景也就两三个,所以我在需要批量注册的组件对应的文件夹就放置这个一个index.js就能实现了,如果实际场景不想放那么多,可以自行稍微改造下,传个路径进去,我Vue3版本就是这样实现的

Vue3 实现

基于 Vite

const components = import.meta.glob("./*.vue");
//注意 :  import.meta.glob 不支持变量,

Vue3 使用 组合式 ,方法里也用到了Vite的语法,首页也要把核心代码封装到 dynamicComponents.js里面

详细如下

// utils/dynamicComponents.js
import { defineAsyncComponent } from 'vue';
function loadComponentsFromFolder(folderPath) {
  const components = {};
  let modules = import.meta.glob('@/components/form-designer/widget/*.vue', { eager: false });
  if (folderPath == 'widgetArrt') {
    modules = import.meta.glob('@/components/form-designer/widget/widget-attr/*.vue', { eager: false });
  }
  for (const path in modules) {
    const componentName = path.match(/\/([^/]+)\.vue$/)[1];
    components[componentName] = defineAsyncComponent(modules[path]);
  }
  return components;
}
export default loadComponentsFromFolder;

这个并不完美,理想中应该是根据传参(需要动态注册的组件所在文件夹路径)来实现,但是,如下目前好像并不支持:

// utils/dynamicComponents.js
function loadComponentsFromFolder(folderPath) {
   //省略...
    modules = import.meta.glob(`${folderPath}/*.vue`, { eager: false   });
   //省略...
}
export default loadComponentsFromFolder;

这样写会报错,提示import.meta.glob不支持变量.

[plugin:vite:import-glob] Invalid glob import syntax:
 Expected glob to be a string, but got dynamic template literal
 //大致意思: 只能使用文本,而我们的 path 使用了变量,所以会报错.

这个有其他解决办法,待会下面会说到,因为我在该项目批量注册应用场景不多,所以我就直接传参判断来写死了.
.接下来就是引用了,如下图:
在这里插入图片描述
至此,就实现批量动态注册了,另外注意, 组件集合不要用绑定模式,虽然不报错,但是会报黄提示影响效率

 // let components =ref({})  //不要写成响应式的了,会有性能风险提示
 let components = {} 
 components = loadComponentsFromFolder('widget')

最后

用其他办法来解决这个问题吧,有点复杂,有更好办法的小伙伴可以留言~

使用 fs 模块读取文件列表:
在 Node.js 环境中使用 fs 模块读取指定文件夹下的文件列表。
将文件列表传递给前端,前端再使用 import() 动态导入这些文件。
前端动态导入:

前端根据接收到的文件列表动态导入组件。
实现步骤
1. 后端读取文件列表
首先,在 Vite 项目的 vite.config.js 或者单独的 Node.js 脚本中,使用 fs 模块读取文件列表,并将结果暴露给前端。

javascript
// vite.config.js 或者单独的 Node.js 脚本
const fs = require('fs');
const path = require('path');

function getComponentPaths(folderPath) {
  const baseFolderPath = path.resolve(__dirname, 'src/components/form-designer/widget/');
  const fullFolderPath = folderPath ? path.join(baseFolderPath, folderPath) : baseFolderPath;

  const files = fs.readdirSync(fullFolderPath);
  const componentPaths = files
    .filter(file => file.endsWith('.vue'))
    .map(file => path.join(fullFolderPath, file));

  return componentPaths.map(p => p.replace(/\\/g, '/').replace(path.resolve(__dirname, 'src/'), '@/'));
}

module.exports = {
  getComponentPaths,
};
2. 前端动态导入
在前端,使用 import() 动态导入这些文件。

javascript
// utils/dynamicComponents.js
import { defineAsyncComponent } from 'vue';

const componentCache = {};

async function loadComponentsFromFolder(folderPath) {
  // 检查缓存
  if (componentCache[folderPath]) {
    return componentCache[folderPath];
  }

  // 获取文件路径列表
  const componentPaths = await fetchComponentPaths(folderPath);

  const components = {};

  // 动态导入模块
  await Promise.all(componentPaths.map(async (path) => {
    const componentName = path.match(/\/([^/]+)\.vue$/)[1];
    components[componentName] = defineAsyncComponent(() => import(path));
  }));

  // 缓存结果
  componentCache[folderPath] = components;

  return components;
}

async function fetchComponentPaths(folderPath) {
  // 这里假设你有一个 API 端点来获取文件路径列表
  const response = await fetch(`/api/get-component-paths?folderPath=${folderPath}`);
  const data = await response.json();
  return data.paths;
}

export default loadComponentsFromFolder;
3. 创建 API 端点
在 Vite 项目中创建一个简单的 API 端点来返回文件路径列表。

javascript
// server/index.js
const express = require('express');
const { getComponentPaths } = require('../vite.config');

const app = express();
const port = 3000;

app.get('/api/get-component-paths', (req, res) => {
  const folderPath = req.query.folderPath;
  const paths = getComponentPaths(folderPath);
  res.json({ paths });
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});
使用示例
在组件或页面中使用 loadComponentsFromFolder 函数时,只需传递不同的 folderPath 参数即可动态注册不同路径下的组件。

javascript
// 在某个 Vue 组件中使用
<script setup>
import { ref, onMounted } from 'vue';
import loadComponentsFromFolder from '@/utils/dynamicComponents';

const folderPath = 'widgetAttr'; // 可以根据实际需求动态设置
const dynamicComponents = ref({});

onMounted(async () => {
  dynamicComponents.value = await loadComponentsFromFolder(folderPath);
});
</script>

<template>
  <div>
    <component v-for="(component, name) in dynamicComponents" :is="component" :key="name"></component>
  </div>
</template>
注意事项
文件路径处理:

确保文件路径在前后端一致,特别是在 Windows 系统中,路径分隔符需要转换。
API 端点:

确保 API 端点能够正确返回文件路径列表。
性能优化:

如果组件数量较多,可以考虑使用懒加载和缓存机制来优化性能。
通过这种方式,你可以根据路径参数动态注册不同文件夹下的组件,而不需要使用 if-else 判断。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2242583.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AndroidStudio-Activity的生命周期

一、Avtivity的启动和结束 从当前页面跳到新页面&#xff0c;跳转代码如下&#xff1a; startActivity(new Intent(源页面.this&#xff0c;目标页面.class))&#xff1b; 从当前页面回到上一个页面&#xff0c;相当于关闭当前页面&#xff0c;返回代码如下&#xff1a; finis…

DB-GPT系列(四):DB-GPT六大基础应用场景part1

一、基础问答 进入DB-GPT后&#xff0c;再在线对话默认的基础功能就是对话功能。这里我们可以和使用通义千问、文心一言等在线大模型类似的方法&#xff0c; 来和DB-GPT进行对话。 但是值得注意的是&#xff0c;DB-GPT的输出结果是在内置提示词基础之上进行的回答&#xff0c…

对PolyMarket的突袭

一天清晨六点&#xff0c;美国联邦调查局的探员冲进了纽约市的一间公寓。这间公寓的主人是26岁的Shane Copeland&#xff0c;一个有着凌乱头发的年轻人&#xff0c;也是一个加密货币狂热者。他运营着一个名为PolyMarket的网站——一个允许用户YZ全球事件结果的平台&#xff0c;…

DB_redis数据一致性(三)

前言 以mysql_redis 为例 介绍 数据一致性 1:数据一致行&#xff08;单进程/单线程&#xff09; 这个没什么说的&#xff0c;都是串行 2:数据一致行(多进程/多线程) 读的逻辑&#xff0c;先读缓存&#xff0c;缓存没有的话&#xff0c;就读数据库&#xff0c;然后取出数据后…

Jdbc学习笔记(三)--PreparedStatement对象、sql攻击(安全问题)

目录 &#xff08;一&#xff09;使用PreparedStatement对象的原因&#xff1a; 使用Statement对象编写sql语句会遇到的问题 ​编辑 &#xff08;二&#xff09;sql攻击 1.什么是sql攻击 2.演示sql攻击 &#xff08;三&#xff09;防止SQL攻击 1.PreparedStatement是什么 …

对称加密算法DES的实现

一、实验目的 1、了解对称密码体制基本原理 2、掌握编程语言实现对称加密、解密 二、实验原理 DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位&#xff0c;产生最大 64 位的分组大小。这是一个迭代的分组密码&#xff0c;使用称为 Feistel 的技术&#xff0c;其中将加密…

【Hadoop实训】Hive 数据操作②

延续上一篇文章&#xff0c;不懂的宝子们请看以下链接&#xff1a; 【Hadoop实训】Hive 数据操作①-CSDN博客 目录 一、Group by 语句 (1)、计算emp表每个部门的平均工资 (2)、计算emp表每个部门中每个岗位的最高工资 二、Having 语句 (1)、求每个部门的平均工资 (2)、求每个…

centos7 升级openssl 与升级openssh 安装卸载 telnet-server

前言&#xff1a; 服务器被安全扫描&#xff0c;扫出了漏洞需要修复&#xff0c;根据提示将openssh升级为9.8p1的版本&#xff0c;同时需要升级openssl&#xff0c;但是升级openssh可能会导致ssh连接失败&#xff0c;从而无法继续操作&#xff0c;特别是远程机房尤为危险&#…

Notepad++的完美替代

由于Notepad的作者曾发表过可能在开发者代码中植入恶意软件的言论&#xff0c;他备受指责。在此&#xff0c;我向大家推荐一个Notepad的完美替代品——NotepadNext和Notepad--。 1、NotepadNext NotepadNext的特点&#xff1a; 1、跨平台兼容性 NotepadNext基于Electron或Qt…

大语言模型LLM综述

一、LM主要发展阶段 1.1、统计语言模型SLM 基于统计学习方法&#xff0c;基本思想是基于马尔可夫假设HMM建立词概率预测模型。如n-gram语言模型 1.2、神经语言模型NLM 基于神经网络来做词的分布式表示。如word2vec模型 1.3、 预训练语言模型PLM 预训练一个网络模型来做词表…

腾讯IM web版本实现迅飞语音听写(流式版)

本文基于TUIKit Demo项目集成迅飞语音听写&#xff08;流式版&#xff09;功能&#xff1a; 主要代码&#xff1a; // \src\TUIKit\components\TUIChat\message-input\index.vue <template><!-- 录音按钮 --><div touchstart.stop"touchstart" />…

2024140读书笔记|《作家榜名著:生如夏花·泰戈尔经典诗选》——你从世界的生命的溪流浮泛而下,终于停泊在我的心头

2024140读书笔记|《作家榜名著&#xff1a;生如夏花泰戈尔经典诗选》——你从世界的生命的溪流浮泛而下&#xff0c;终于停泊在我的心头 《作家榜名著&#xff1a;生如夏花泰戈尔经典诗选》[印]泰戈尔&#xff0c;郑振铎译&#xff0c;泰戈尔的诗有的清丽&#xff0c;有的童真&…

物理hack

声明 声明 文章只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 ✍&#x1f3fb;作者简介&#xff1a;致力于网络安全领域&#xff0c;目前作为一名学习者&#xff0c;很荣…

【运维实施资料集】软件全套运维,实施管理方案,运维建设方案,运维检查单,软件项目运维方案(word原件)

1 编制目的 2 系统运行维护 2.1 系统运维内容 2.2 日常运行维护方案 2.2.1 日常巡检 2.2.2 状态监控 2.2.3 系统优化 2.2.4 软件系统问题处理及升级 2.2.5 系统数据库管理维护 2.2.6 灾难恢复 2.3 应急运行维护方案 2.3.1 启动应急流程 2.3.2 成立应急小组 2.3.3 应急处理过程 …

大学语文教材电子版(第十一版)教学用书PDF及课件

大学语文课件&#xff1a;https://caiyun.139.com/m/i?005CiDusEVWnR 《大学语文》&#xff08;第十一版&#xff09;主编&#xff1a;徐中玉 齐森华 谭帆。 大学语文教材电子版教师用书PDF第一课《齐桓晋文之事》艺术赏析&#xff1a; 孟子四处游说&#xff0c;养成善辩的…

java模拟键盘实现selenium上下左右键 table中的左右滚动条实现滚动

在这篇文章中&#xff0c;我们将学习如何使用Java编程语言模拟键盘输入&#xff0c;特别是模拟上下左右方向键的操作。这是一个很有趣的项目&#xff0c;尤其适合刚入行的开发者。我们将分步进行&#xff0c;接下来&#xff0c;我们会通过表格展示整个实现过程&#xff0c;然后…

量子计算与人工智能的交汇:科技未来的新引擎

引言 在当今飞速发展的科技世界&#xff0c;人工智能&#xff08;AI&#xff09;和量子计算无疑是最受瞩目的两大前沿领域。人工智能凭借其在数据处理、模式识别以及自动化决策中的强大能力&#xff0c;已经成为推动各行业数字化转型的重要力量。而量子计算则通过颠覆传统计算机…

【Oracle篇】掌握SQL Tuning Advisor优化工具:从工具使用到SQL优化的全方位指南(第六篇,总共七篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

变分自编码器(VAE, Variational Autoencoder)

代码说明 VAE 模型结构&#xff1a; 编码器将输入数据&#xff08;如 MNIST 图像&#xff09;映射到潜在空间&#xff0c;生成均值 (mu) 和对数方差 (logvar)。 通过重新参数化技巧 (reparameterize) 从正态分布中采样潜在向量 z。 解码器将潜在向量 z 映射回原始空间&#xf…

DataWorks on EMR StarRocks,打造标准湖仓新范式

在大数据领域&#xff0c;数据仓库和实时分析系统扮演着至关重要的角色。DataWorks 基于大数据引擎&#xff0c;为数据仓库/数据湖/湖仓一体等解决方案提供统一的全链路大数据开发治理平台&#xff0c;为用户带来智能化的数据开发和分析体验。而阿里云提供的 EMR Serverless St…