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

用Vue3.0 写过组件吗?如果想实现一个 Modal你会怎么设计?

一、组件设计

组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念(组件)来实现开发的模式

现在有一个场景,点击新增与编辑都弹框出来进行填写,功能上大同小异,可能只是标题内容或者是显示的主体内容稍微不同

这时候就没必要写两个组件,只需要根据传入的参数不同,组件显示不同内容即可

这样,下次开发相同界面程序时就可以写更少的代码,意义着更高的开发效率,更少的 Bug 和更少的程序体积

二、需求分析

实现一个Modal组件,首先确定需要完成的内容:

  • 遮罩层
  • 标题内容
  • 主体内容
  • 确定和取消按钮

主体内容需要灵活,所以可以是字符串,也可以是一段 html 代码

特点是它们在当前vue实例之外独立存在,通常挂载于body之上

除了通过引入import的形式,我们还可通过API的形式进行组件的调用

还可以包括配置全局样式、国际化、与typeScript结合

三、实现流程

首先看看大致流程:

  • 目录结构
  • 组件内容
  • 实现 API 形式
  • 事件处理
  • 其他完善

目录结构

Modal组件相关的目录结构

├── plugins
│   └── modal
│       ├── Content.tsx // 维护 Modal 的内容,用于 h 函数和 jsx 语法
│       ├── Modal.vue // 基础组件
│       ├── config.ts // 全局默认配置
│       ├── index.ts // 入口
│       ├── locale // 国际化相关
│       │   ├── index.ts
│       │   └── lang
│       │       ├── en-US.ts
│       │       ├── zh-CN.ts
│       │       └── zh-TW.ts
│       └── modal.type.ts // ts类型声明相关

因为 Modal 会被 app.use(Modal) 调用作为一个插件,所以都放在plugins目录下

组件内容

首先实现modal.vue的主体显示内容大致如下

<Teleport to="body" :disabled="!isTeleport"><div v-if="modelValue" class="modal"><divclass="mask":style="style"@click="maskClose && !loading && handleCancel()"></div><div class="modal__main"><div class="modal__title line line--b"><span>{{ title || t("r.title") }}</span><spanv-if="close":title="t('r.close')"class="close"@click="!loading && handleCancel()">✕</span></div><div class="modal__content"><Content v-if="typeof content === 'function'" :render="content" /><slot v-else>{{ content }}</slot></div><div class="modal__btns line line--t"><button :disabled="loading" @click="handleConfirm"><span class="loading" v-if="loading"> ❍ </span>{{ t("r.confirm") }}</button><button @click="!loading && handleCancel()">{{ t("r.cancel") }}</button></div></div></div>
</Teleport>

最外层上通过Vue3 Teleport 内置组件进行包裹,其相当于传送门,将里面的内容传送至body之上

并且从DOM结构上来看,把modal该有的内容(遮罩层、标题、内容、底部按钮)都实现了

关于主体内容

<div class="modal__content"><Content v-if="typeof content==='function'":render="content" /><slot v-else>{{content}}</slot>
</div>

可以看到根据传入content的类型不同,对应显示不同得到内容

最常见的则是通过调用字符串和默认插槽的形式

// 默认插槽
<Modal v-model="show"title="演示 slot"><div>hello world~</div>
</Modal>// 字符串
<Modal v-model="show"title="演示 content"content="hello world~" />

通过 API 形式调用Modal组件的时候,content可以使用下面两种

  • h 函数
$modal.show({title: '演示 h 函数',content(h) {return h('div',{style: 'color:red;',onClick: ($event: Event) => console.log('clicked', $event.target)},'hello world ~');}
});
  • JSX
$modal.show({title: '演示 jsx 语法',content() {return (<divonClick={($event: Event) => console.log('clicked', $event.target)}>hello world ~</div>);}
});

实现 API 形式

那么组件如何实现API形式调用Modal组件呢?

Vue2中,我们可以借助Vue实例以及Vue.extend的方式获得组件实例,然后挂载到body

import Modal from './Modal.vue';
const ComponentClass = Vue.extend(Modal);
const instance = new ComponentClass({ el: document.createElement("div") });
document.body.appendChild(instance.$el);

虽然Vue3移除了Vue.extend方法,但可以通过createVNode实现

import Modal from './Modal.vue';
const container = document.createElement('div');
const vnode = createVNode(Modal);
render(vnode, container);
const instance = vnode.component;
document.body.appendChild(container);

Vue2中,可以通过this的形式调用全局 API

export default {install(vue) {vue.prototype.$create = create}
}

而在 Vue3 的 setup 中已经没有 this 概念了,需要调用app.config.globalProperties挂载到全局

export default {install(app) {app.config.globalProperties.$create = create}
}

事件处理

下面再看看看Modal组件内部是如何处理「确定」「取消」事件的,既然是Vue3,当然采用Compositon API 形式

// Modal.vue
setup(props, ctx) {let instance = getCurrentInstance(); // 获得当前组件实例onBeforeMount(() => {instance._hub = {'on-cancel': () => {},'on-confirm': () => {}};});const handleConfirm = () => {ctx.emit('on-confirm');instance._hub['on-confirm']();};const handleCancel = () => {ctx.emit('on-cancel');ctx.emit('update:modelValue', false);instance._hub['on-cancel']();};return {handleConfirm,handleCancel};
}

在上面代码中,可以看得到除了使用传统emit的形式使父组件监听,还可通过_hub属性中添加 on-cancelon-confirm方法实现在API中进行监听

app.config.globalProperties.$modal = {show({}) {/* 监听 确定、取消 事件 */}
}

下面再来目睹下_hub是如何实现

// index.ts
app.config.globalProperties.$modal = {show({/* 其他选项 */onConfirm,onCancel}) {/* ... */const { props, _hub } = instance;const _closeModal = () => {props.modelValue = false;container.parentNode!.removeChild(container);};// 往 _hub 新增事件的具体实现Object.assign(_hub, {async 'on-confirm'() {if (onConfirm) {const fn = onConfirm();// 当方法返回为 Promiseif (fn && fn.then) {try {props.loading = true;await fn;props.loading = false;_closeModal();} catch (err) {// 发生错误时,不关闭弹框console.error(err);props.loading = false;}} else {_closeModal();}} else {_closeModal();}},'on-cancel'() {onCancel && onCancel();_closeModal();}});
}
};

其他完善

关于组件实现国际化、与typsScript结合,大家可以根据自身情况在此基础上进行更改

参考文献

  • https://segmentfault.com/a/1190000038928664

相关文章:

用Vue3.0 写过组件吗?如果想实现一个 Modal你会怎么设计?

一、组件设计 组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念&#xff08;组件&#xff09;来实现开发的模式 现在有一个场景&#xff0c;点击新增与编辑都弹框出来进行填写&#xff0c;功能上大同小异&#xff0c;可能只是标题内容或者是显示的主体内容稍微不同 …...

ArmSoM-W3之RK3588硬编解码MPP环境配置

1. 简介 瑞芯微提供的媒体处理软件平台&#xff08;Media Process Platform&#xff0c;简称 MPP&#xff09;是适用于瑞芯微芯片系列的 通用媒体处理软件平台。该平台对应用软件屏蔽了芯片相关的复杂底层处理&#xff0c;其目的是为了屏蔽不 同芯片的差异&#xff0c;为使用者…...

源码解析flink文件连接源TextInputFormat

背景&#xff1a; kafka的文件系统数据源可以支持精准一次的一致性,本文就从源码看下如何TextInputFormat如何支持状态的精准一致性 TextInputFormat源码解析 首先flink会把输入的文件进行切分&#xff0c;分成多个数据块的形式&#xff0c;每个数据源算子任务会被分配以读取…...

SQL ORDER BY Keyword(按关键字排序)

SQL ORDER BY 关键字 ORDER BY 关键字用于按升序或降序对结果集进行排序。 ORDER BY 关键字默认情况下按升序排序记录。 如果需要按降序对记录进行排序&#xff0c;可以使用DESC关键字。 SQL ORDER BY 语法 SELECT column1, column2, ... FROM table_name ORDER BY column1, …...

光伏三相并网逆变器的控制策略与性能分析(Simulink仿真实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

【网络安全 --- xss-labs靶场】xss-labs靶场安装详细教程,让你巩固对xss漏洞的理解及绕过技巧和方法(提供资源)

一&#xff0c;资源下载准备 1-1 VMware 16.0 安装请参考以下博客&#xff0c;若已经安装请忽略&#xff1a; 【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;-CSDN博客【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;…...

蓝桥每日一题(day 3: 蓝桥587.约数个数)--数学--easy

题目 解题核心&#xff1a; 分解质因数&#xff0c;每个质因数的次方1的累乘积就是anscode #include <iostream> #include<algorithm> #include<unordered_map> //# #include<> typedef long long LL; const int N 110, MOD 1e9 7;using namespac…...

深入剖析Java类加载过程:探寻类加载器的奥秘

摘要: 一个java文件从被加载到被卸载这个生命过程&#xff0c;总共要经历4个阶段&#xff1a; 加载->链接&#xff08;验证准备解析&#xff09;->初始化&#xff08;使用前的准备&#xff09;->使用->卸载 其中类加载过程包括加载、验证、准备、解析和初始化五个阶…...

PHP yield

概念&#xff1a; Generator&#xff1a;带 yield的function yield&#xff1a;Generator或task的中断关键字&#xff0c;执行到yield时一次调度周期执行完即阻塞&#xff0c;并返回右侧表达式结果&#xff0c;等待下一次调度器运行next()或迭代遍历才会继续往下执行&#xff0…...

react antd实现upload上传文件前form校验,同时请求带data

最近的需求&#xff0c;两个下拉框是必填项&#xff0c;点击上传按钮&#xff0c;如果有下拉框没选要有提示&#xff0c;如图 如果直接使用antd的Upload组件&#xff0c;一点击文件选择的窗口就打开了&#xff0c;哪怕在Button里再加点击事件&#xff0c;也只是&#xff08;几乎…...

echars 设置滚动条演示,

dataZoom: [// 滑动条{zoomLock:true,xAxisIndex: 0, // 这里是从X轴的0刻度开始type: "slider", // 这个 dataZoom 组件是 slider 型 dataZoom 组件startValue: 0, // 从头开始。endValue: 20, // 一次性展示几个。// fillerColor: "#023661", // 选中范围…...

代码随想录算法训练营第五十八天|583.两个字符串的删除操作 、72. 编辑距离

代码随想录算法训练营第五十八天|583.两个字符串的删除操作 、72. 编辑距离 文章目录 代码随想录算法训练营第五十八天|583.两个字符串的删除操作 、72. 编辑距离[toc]583.两个字符串的删除操作求公共部分长度&#xff1a;即最长公共子串 72. 编辑距离 583.两个字符串的删除操作…...

1024网络技术命令汇总(第54课)

1024网络技术命令汇总(第54课) 1 查询命令 display ? display current-configuration //查看全部的配置信息 display interface brief //查看接口的信 display ip interface brief //查看IP地址的接口信息状态 display arp all …...

智慧河湖方案:AI赋能水利水务,构建河湖智能可视化监管大数据平台

一、方案背景 我国江河湖泊众多&#xff0c;水系发达。伴随着经济社会快速发展&#xff0c;水生态水环境问题成为群众最关注的民生议题之一。一些河流开发利用已接近甚至超出水环境承载能力&#xff0c;一些地区废污水排放量居高不下&#xff0c;一些地方侵占河道、围垦湖泊等…...

界面组件DevExpress WPF v23.1 - 全面升级文档处理功能

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…...

【C语言必知必会 | 第八篇】一文带你精通循环结构

引言 C语言是一门面向过程的、抽象化的通用程序设计语言&#xff0c;广泛应用于底层开发。它在编程语言中具有举足轻重的地位。 此文为【C语言必知必会】系列第八篇&#xff0c;进行C语言循环结构的专项练习&#xff0c;结合专题优质题目&#xff0c;带领读者从0开始&#xff0…...

同一个线程池执行不同类型的任务

1、同一个线程池可以执行不同的任务类型&#xff0c;也可以带返回值&#xff0c;也可以不带返回值的 import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.vip.vman.result.BasicResult; import lombok.extern.slf4j.Slf4j; import org.springframewor…...

GEO生信数据挖掘(八)富集分析(GO 、KEGG、 GSEA 打包带走)

第六节&#xff0c;我们使用结核病基因数据&#xff0c;做了一个数据预处理的实操案例。例子中结核类型&#xff0c;包括结核&#xff0c;潜隐进展&#xff0c;对照和潜隐&#xff0c;四个类别。第七节延续上个数据&#xff0c;进行了差异分析。 本节对差异基因进行富集分析。 …...

高校教务系统登录页面JS分析——华南理工大学

高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文&#xff0c;你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习&#xff0c;勿用于非法用途。 一、密码加…...

人工智能之PyTorch数据操作-Python版

PyTorch数据操作 # 导入PyTorch import torch [张量表示一个由数值组成的数组&#xff0c;这个数组可能有多个维度]。 具有一个轴的张量对应数学上的向量&#xff08;&#xff09;&#xff1b; 具有两个轴的张量对应数学上的矩阵&#xff08;matrix&#xff09;&#xff1b;…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...