当前位置: 首页 > 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高手可以无视下…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...