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

[element plus] 对话框组件再封装使用 - vue

学习关键语句:
饿了么组件dialog组件使用
dialog组件二次封装
vue3中封住的组件使用update触发更新
vue3中封装组件使用v-model:属性值来传值

写在前面

这是我遇到的一个页面需求 , 其中一个对话框的内容是很常用的 , 所以我将它封装出来才写的一篇文章
现在给出如下需求:

封装一个组件 , 要求每次选择用户的时候 , 能从组件返回选择的用户id数组
并且能在选择用户是看到选择了哪些用户

  • 如果你只是想看如何封装组件 , 请根据目录点击 ‘封装对话框组件’ 这个内容

文章末尾附带本文项目文件链接

开始

提示 : 本项目使用 vite 创建的 vue3 项目 , 使用 express 创建的后端

创建项目文件夹

随意新建一个文件夹 , 起名为 test , 在该文件夹下 , 再新建一个文件夹为 server

在这里插入图片描述

开启终端 , 输入创建项目命令

npm create vite

依次输入项目名称 dialog , 框架选择 Vue , 语言选择 typescript
在这里插入图片描述

创建完成后 , 根据提示 输入提示的命令

cd dialog
npm install
npm run dev

在这里插入图片描述
点击打开最后这个网址就完成了项目最初的创建

现在我们来创建后端服务器
打开终端 , 进入 server 文件夹 , 输入以下命令

npm init

在这里插入图片描述
测试使用 , 全部按回车默认过去就OK了
命令行中安装依赖

npm install

同时我们再创建一个文件 起名为 app.js
全部创建完后的目录如下
在这里插入图片描述

安装库和配置

现在需要在前端和后端中各安装需要的库
其中 , 前端需要安装 elementUI 和 axios
后端需要安装 express , cors , body-parser 和 connect-multiparty

注意 安装依赖前请确定在对的终端下 , 不可下错了位置

后端

优先进行后端的配置

  1. 安装 express 制作服务器
npm install express --save
  1. 安装 cors 解决跨域
npm install cors --save
  1. 引入中间件解决读取参数问题
npm install body-parser --save
npm install connect-multiparty --save

配置完成之后我们来写服务器文件 app.js

app.js

// 导入 express
const express = require('express')
// 创建 app
const app = express()
// 设置跨域访问
const cors = require('cors')
app.use(cors())
// 处理POST参数
const bodyParser = require('body-parser')
const multiparty = require('connect-multiparty')
// 处理 x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended:true
}));
// 处理 application/json
app.use(bodyParser.json())
// 处理 mutipart/form-data
app.use(multiparty())// 测试接口能否正常调用
app.get('/hello', (req, res) => {res.send("Hello shaoyahu !")
})// 我们写一个获取用户信息的接口
// 模拟数据库中的用户数据
let db = [{ id: 1, name: '张一' },{ id: 2, name: '张二' },{ id: 3, name: '张三' },{ id: 4, name: '熊大' },{ id: 5, name: '熊二' },{ id: 6, name: '熊三' },{ id: 7, name: '李三' },{ id: 8, name: '李四' },
]
app.post('/getUserData', (req, res) => {let txt = req.body.namelet data = db.filter(item => {return item.name.includes(txt)})res.send({status: 200,data,msg: '获取成功'})
})// 启动
app.listen(3000, () => {console.log('express server running at http://127.0.0.1:' + 3000);
})

写好服务器文件后在终端输入如下命令启动服务器

node app.js

当控制台打印出我们设置的语句时表示服务器已经启动成功
在这里插入图片描述
现在简单测试一下调用接口
在浏览器中输入

http://localhost:3000/hello

如果出现 Hello shaoyahu ! 就说明接口调用成功了

在这里插入图片描述
那么后端先写到这里 , 我们现在来看前端

前端

  1. 安装element plus
npm install element-plus --save

安装完毕后打开 main.ts 文件进行引入和挂载

import { createApp } from 'vue'
import ElementPlus from 'element-plus'	// 加入
import 'element-plus/dist/index.css'	// 加入
import App from './App.vue'const app = createApp(App)	// 修改
app.use(ElementPlus)		// 修改
app.mount('#app')			// 修改

这样就能使用饿了么的组件了

  1. 安装 axios
npm install axios --save

在 src 目录下新建文件 axios.ts

axios.ts
进行简单的封装 , 不添加拦截器

import axios from 'axios'const service = axios.create({// 根据刚才的后端地址和端口配置写出请求基础路径baseURL: 'http://localhost:3000'
})export default service

在 src 目录下新建文件夹起名 api
在 api 文件夹中新建文件起名为 user.ts

user.ts
专门存放和用户有关的接口请求
我们写一个获取用户信息的请求

import axios from '../axios'// 获取用户信息
export function getUserData(data: { name: string }){return axios.post('/getUserData', data)
}

axios 相关的操作完成后目录结构如下图
![在这里插入图片描述](https://img-blog.csdnimg.cn/9b9d31c0af2d4168a5cf42c2fd02f121.png在这里插入图片描述

编写页面内容

我们将 App.vue 页面的内容清空 , 写入一个简单的提示词 , 输入框和按钮

App.vue

<template><div class="index"><span>选中的用户</span><el-input v-model="searchTxt" type="textarea"style="width: 220px;" disabled :placeholder="'请选择用户'" /><el-button @click="toSelectPerson">选择用户</el-button></div>
</template><script setup lang='ts'>
import { ref } from "vue";
let searchTxt = ref('')
const toSelectPerson = () => {}
</script>

在这里插入图片描述
我们的逻辑是 , 点击选择用户按钮 , 打开一个对话框 , 在对话框中我们选择好需要的用户后关闭对话框 , 将在对话框中选中的用户在输入框中展现

那么 , 由于这个选择人物的对话框会在多处使用到 , 所以我们现在就来封装一个对话框组件吧

封装对话框组件

我们在 src 下的 components 文件夹中新建文件 起名为 myDialog.vue

myDialog.vue

需要注意的点如下

  • 开启关闭对话框的方法必须使用 v-model: 来给属性值
  • 饿了么组件的对话框原始的 v-model 需要修改成 :model-value 才不会报错
  • 这个文件里的样式我没写在下方 , 但是末尾文件中会有样式
  • 通过点击遮罩层关闭掉对话框的方式虽然可以关闭对话框 , 但实际上传入的值仍然为 true , 解决方法有两个 , 第一个是通用的 , 将打开对话框和关闭对话框的方法写在组件上 , 通过操控组件来打开和关闭对话框 , 第二个办法则是参考了饿了么组件提供的一个属性 before-close , 在这个属性中 , 我们手动 emit 传入的值修改为 false 就可以了
<template><el-dialog :model-value="props.selectUserShow":title="props.title" :width="props.width":draggable="drag" :before-close="beforeClose"><slot><div><span>搜索 : </span><el-input v-model="searchTxt" :placeholder="'输入关键词'"><template #append><el-button @click="searchPerson">查询</el-button></template></el-input><div><div><span>选择用户</span></div><div><div v-for="item, index in data" :key="index" style="margin: 20px;"><el-checkbox v-model="item.checked" :label="item.name" size="large" @change="select(item)" /></div></div><div><span>已选择用户</span><div>{{ selectedTxt }}</div></div></div></div></slot><template #footer><span><el-button type="primary" @click="emit('confirm', selectedData)">确定</el-button><el-button @click="emit('update:selectUserShow', false)">取消</el-button></span></template></el-dialog>
</template><script setup lang='ts'>
import { computed, ref } from 'vue'
import { getUserData } from '../api/user.js'
export interface IData {id: number,name: string,checked?: boolean
}
const props = defineProps({// 控制组件的显示与隐藏selectUserShow: {type: Boolean,default: false,required: true},// 传进来的已经选择了的用户数组selectUserList: {type: Array<IData>,default: [],required: true},title: {type: String,default: ''},width: {type: String,default: '80%'},drag: {type: Boolean,default: true}
})
const emit = defineEmits(['confirm', 'update:selectUserShow'])
// 查询用户的关键词
let searchTxt = ref('')
// 查询结果数据
let data = ref<IData[]>([])
// 已经选择的数据数组
let selectedData = ref<IData[]>(props.selectUserList)
let selectedTxt = computed(() => {let t = ''selectedData.value.map((item: IData) => {t += `${item.name} , `})t = t.substring(0, t.length - 2)return t
})
// 查询用户
const searchPerson = () => {getUserData({ name: searchTxt.value }).then((res: any) => {data.value = res.data.dataaddSelectedStatus(data.value)})
}
// 选择用户
const select = (obj: IData) => {if (obj.checked) {selectedData.value.push(obj)} else {selectedData.value = selectedData.value.filter((item: IData) => {return item.id !== obj.id})}
}
// 给所有人添加选中状态
// 需要判断查询出来的用户中是否已经有被选中的用户
function addSelectedStatus(data: IData[]) {data.forEach((item: any) => {let flag = selectedData.value.some((item2: IData) => {return item2.id === item.id})if (flag) {item.checked = true} else {item.checked = false}})
}
// 关闭对话框之前
const beforeClose = (done: Function) => {emit('update:selectUserShow', false)done()
}
searchPerson()
// 导出搜索用户的方法 , 是为了防止一个页面多个查询用户共用一个组件导致已选中的打开无法显示已选中的情况出现 , 使用方法为在打开组件时调用这个方法
defineExpose({searchPerson
})
</script>

这样一个对话框组件就被封装完成了 , 但是由于添加了很多属性和内容 , 所以定制度是比较高的 , 我将所有默认的内容都放在了默认插槽中 , 如果需要另一个对话框的话可以使用插槽覆盖掉原有的内容 , 不过还是建议重新封装一个

补完页面

对话框组件已经封装好了 , 现在我们回头去使用这个组件

App.vue

<template><div class="index"><span>选中的用户</span><el-input v-model="userTxt" type="textarea" style="width:220px" disabled :placeholder="'请选择用户'" /><el-button @click="toSelectPerson">选择用户</el-button></div>{{ selectUserList }}<myDialog v-model:selectUserShow="selectUserShow" :selectUserList="selectUserList" @confirm="confirmUser"></myDialog>
</template><script setup lang='ts'>
import { ref } from "vue";
import myDialog, { IData } from './components/myDialog.vue'let userTxt = ref('')
let selectUserShow = ref(false)const toSelectPerson = () => {selectUserShow.value = true
}
let selectUserList = ref<IData[]>([])
const confirmUser = (selectedData: IData[]) => {userTxt.value = ''selectUserShow.value = falseselectUserList.value = selectedDataselectUserList.value.map((item: IData) => {userTxt.value += `${item.name} , `})userTxt.value = userTxt.value.substring(0, userTxt.value.length - 2)
}
</script>

在这里插入图片描述

结束

就这样这个组件就完成了 , 不过不是很建议大家使用传入值来控制组件的显示和隐藏 , 推荐还是使用组件 expose 出的方法来操作

文件链接

最后附上文件链接
https://download.csdn.net/download/shaoyahu/87477013

相关文章:

[element plus] 对话框组件再封装使用 - vue

学习关键语句: 饿了么组件dialog组件使用 dialog组件二次封装 vue3中封住的组件使用update触发更新 vue3中封装组件使用v-model:属性值来传值 写在前面 这是我遇到的一个页面需求 , 其中一个对话框的内容是很常用的 , 所以我将它封装出来才写的一篇文章 现在给出如下需求: 封…...

Markdown基本语法简介

前言&#xff1a;当你在git平台创建一个仓库时&#xff0c;平台会自动创建一个README.md文件&#xff0c;并将它的内容展现在web端页面&#xff0c;方面其他读者查阅。README.md实则是一个适用Markdown语法的文本文件&#xff0c;从他的后缀md即可看出它是Markdown的缩写。在gi…...

分布式服务的接口幂等性如何设计

1.1 概述 所谓幂等: 多次调用方法或者接口不会改变业务状态&#xff0c;可以保证重复调用的结果和单次调用的结果一致。 基于RESTful API的角度对部分常见类型请求的幂等性特点进行分析 举个例子: 假如你有个某多多 有个服务 服务提供一个接口&#xff0c;结果这个服务部署在…...

视频流截取保存到本地路径(打包jar包CMD运行)

需求&#xff1a;现在有一批https的监控视频流URL&#xff0c;需要对视频流进行每三秒截屏一次&#xff0c;并保存到本地路径&#xff0c;png格式&#xff0c;以当前时间命名。代码&#xff1a;import org.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.Fra…...

mysql索引失效的几种情况

失效的几种情况 1、select * from xxx 2、索引列上有计算 3、索引列上有函数 4、like左边包含‘%’ 5、使用or关键字 6、not in和not exists 7、order by 8、不满足最左匹配原则 给code、age和name这3个字段建好联合索引&#xff1a;idx_code_age_name。 该索引字段的顺…...

Windows下载安装Redis的详细步骤

目录 一、概述 1.redis的版本维护介绍 2.msi安装包和压缩包的优点和缺点 二、操作步骤 三、测试是否安装成功&#xff08;查看版本&#xff09; 四、获取资源 一、概述 1.redis的版本维护介绍 Redis的官网只提供Linux系统的下载。但是微软的技术团队长期开发和维护着这…...

【蓝桥杯每日一题】差分算法

&#x1f34e; 博客主页&#xff1a;&#x1f319;披星戴月的贾维斯 &#x1f34e; 欢迎关注&#xff1a;&#x1f44d;点赞&#x1f343;收藏&#x1f525;留言 &#x1f347;系列专栏&#xff1a;&#x1f319; 蓝桥杯 &#x1f319;我与杀戮之中绽放&#xff0c;亦如黎明的花…...

MyBatis Plus 数据库字段加密处理

目录1.场景介绍2.Maven依赖2.AESUtil.java 加解密工具类3.字段处理类4.修改 MyBatis Plus 查询4.1 修改表对应实体类4.2 修改加密字段对应属性4.3 修改 xml 使用 ResultMap4.4 修改 xml 中 el 表达式5.测试结果6.MyBatis Plus 缺陷补充&#xff1a;测试实例1 查询测试1.1 查询信…...

openpose在win下环境配置

1.下载OpenPose库 以下二选一进行下载源码 (1)git进行下载 打开GitHub Desktop或者Powershell git clone https://github.com/CMU-Perceptual-Computing-Lab/openpose cd openpose/ git submodule update --init --recursive --remote(2)在github上手动下载 由于下载环境问…...

【剑指offer-C++】JZ16:数值的整数次方

【剑指offer】JZ16&#xff1a;数值的整数次方题目描述解题思路题目描述 描述&#xff1a;实现函数 double Power(double base, int exponent)&#xff0c;求base的exponent次方。 注意&#xff1a; 1.保证base和exponent不同时为0。 2.不得使用库函数&#xff0c;同时不需要…...

了解Axios及其运用方式

Axios简介 axios框架全称&#xff08;ajax – I/O – system&#xff09;&#xff1a; 基于promise用于浏览器和node.js的http客户端&#xff0c;因此可以使用Promise API 一、axios是干啥的 说到axios我们就不得不说下Ajax。在旧浏览器页面在向服务器请求数据时&#xff0c;…...

【LeetCode】剑指 Offer(7)

目录 写在前面&#xff1a; 题目剑指 Offer 17. 打印从1到最大的n位数 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 题目&#xff1a;剑指 Offer 18. 删除链表的节…...

Python:try except 异常处理整理

目录 一、try except异常处理的语句格式 二、获取相关异常信息 &#xff08;1&#xff09;sys.exec_info() 三、traceback模块的常用方式 &#xff08;1&#xff09;traceback.print_tb(tb, limitNone, fileNone) 打印指定堆栈异常信息 &#xff08;2&#xff09;tracebac…...

Redis Lua脚本的详细介绍以及使用入门

Redis Lua脚本的详细介绍以及使用入门。 文章目录Redis Lua脚本的引入开源软件的可扩展性Redis的扩展性脚本Redis Lua脚本的基本使用通过EVAL命令执行Lua脚本通过脚本与Redis交互Java中调用Redis Lua脚本Java调用Lua脚本的方式Redis Lua脚本的使用建议脚本缓存脚本缓存稳定性脚…...

synchronized和ReentrantLock有什么区别呢?

第15讲 | synchronized和ReentrantLock有什么区别呢&#xff1f; 从今天开始&#xff0c;我们将进入 Java 并发学习阶段。软件并发已经成为现代软件开发的基础能力&#xff0c;而 Java 精心设计的高效并发机制&#xff0c;正是构建大规模应用的基础之一&#xff0c;所以考察并发…...

SVHN数据集下载及使用方法

街景门牌号数据集&#xff08;SVHN&#xff09;&#xff0c;这是一个现实世界数据集&#xff0c;用于开发目标检测算法。它需要最少的数据预处理过程。它与 MNIST 数据集有些类似&#xff0c;但是有着更多的标注数据&#xff08;超过 600,000 张图像&#xff09;。这些数据是从…...

产业安全公开课:2023年DDoS攻击趋势研判与企业防护新思路

2023年&#xff0c;全球数字化正在加速发展&#xff0c;网络安全是数字化发展的重要保障。与此同时&#xff0c;网络威胁日益加剧。其中&#xff0c;DDoS攻击作为网络安全的主要威胁之一&#xff0c;呈现出连年增长的态势&#xff0c;给企业业务稳定带来巨大挑战。2月21日&…...

Docker 容器命令 和安装各种镜像环境

CentOS安装Docker 1.1.卸载&#xff08;可选&#xff09; 如果之前安装过旧版本的Docker&#xff0c;可以使用下面命令卸载&#xff1a; yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotat…...

【数据结构】顺序表的深度剖析

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;别人可以拷贝我的模式&#xff0c;但不能拷贝我不断往前的激情 &#x1f6f8;C语言专栏&#xff1a;https://blog.csdn.net/vhhhbb/category_12174730.html &#x1f680;数据结构专栏&#xff…...

当面试官问“你的SQL能力怎么样”时,怎么回答才不会掉进应聘陷阱?

在某平台看到一个比较实际的问题&#xff0c;在这里分享给职场新人。 SQL已经是职场最常用的一种编程语言&#xff0c;所以应聘技术或非技术岗位&#xff0c;都可能会被问道一个问题&#xff1a;你的SQL能力怎么样&#xff1f; 对于职场新人来说&#xff08;SQL高手可以无视下…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...