后台数据管理系统 - 项目架构设计-Vue3+axios+Element-plus(0926)

十四、文章分类添加编辑 [element-plus 弹层]

Git仓库:https://gitee.com/msyycn/vue3-hei-ma.git

点击显示弹层

  1. 准备弹层
const dialogVisible = ref(false)<el-dialog v-model="dialogVisible" title="添加弹层" width="30%"><div>我是内容部分</div><template #footer><span class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary"> 确认 </el-button></span></template>
</el-dialog>
  1. 点击事件
<template #extra><el-button type="primary" @click="onAddChannel">添加分类</el-button></template>const onAddChannel = () => {dialogVisible.value = true
}

封装弹层组件 ChannelEdit

添加 和 编辑,可以共用一个弹层,所以可以将弹层封装成一个组件

组件对外暴露一个方法 open, 基于 open 的参数,初始化表单数据,并判断区分是添加 还是 编辑

  1. open({ }) => 添加操作,添加表单初始化无数据
  2. open({ id: xx, … }) => 编辑操作,编辑表单初始化需回显

具体实现:

  1. 封装组件 article/components/ChannelEdit.vue
<script setup>
import { ref } from 'vue'
const dialogVisible = ref(false)const open = async (row) => {dialogVisible.value = trueconsole.log(row)
}defineExpose({open
})
</script><template><el-dialog v-model="dialogVisible" title="添加弹层" width="30%"><div>我是内容部分</div><template #footer><span class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary"> 确认 </el-button></span></template></el-dialog>
</template>
  1. 通过 ref 绑定
const dialog = ref()<!-- 弹窗 -->
<channel-edit ref="dialog"></channel-edit>
  1. 点击调用方法显示弹窗
const onAddChannel = () => {dialog.value.open({})
}
const onEditChannel = (row) => {dialog.value.open(row)
}

ChannelEdit.vue(封装的组件)

<script setup>
import {ref} from 'vue'const dialogVisible = ref(false) //弹层状态// 组件对外暴露一个方法,open ,基于open 传来的参数,区分添加还是编辑
// open ({}) => 表单无需渲染,说明是添加分
// open ({id, name}) => 表单需要渲染,说明是编辑分类
// open调用后,可以打开弹窗
const open = (row) =>{console.log(row)dialogVisible.value = true}
// 向外暴露一个方法,close,关闭弹窗
defineExpose({open
})
</script><template>//弹层<el-dialogv-model="dialogVisible"title="添加弹层"width="500":before-close="handleClose"><div>渲染表单</div><span>我是内容部分  </span><template #footer><div class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="dialogVisible = false">确认</el-button></div></template></el-dialog>
</template>

ArticleChannel.vue

<script setup>
import { artGetChannelsService } from '@/api/article'
import { Delete,Edit } from   '@element-plus/icons-vue'import {ref} from 'vue'
import ChannelEdit from './components/ChannelEdit.vue'
const channelList = ref([]) // 文章分类列表
const loading = ref(false) //加载状态const dialog = ref()
// 获取文章分类列表
const getChannelList = async () => {// 发请求之前先将loading设置为trueloading.value = true// 调用接口const res = await artGetChannelsService()channelList.value = res.data.data// channelList.value = []// 发完请求,关闭loadingloading.value = false// console.log('文章分类列表',channelList.value);}// 调用获取文章分类列表
getChannelList()// 编辑文章分类
const onEditChannel =(row) =>{
// console.log(row,$index)
dialog.value.open({row})
}       // 删除文章分类
const onDelChannel =(row,$index)=>{console.log(row,$index)}
const onAddChannel = () => {dialog.value.open({})
}</script><template><div><!-- 按需引入 --><page-container title="文章分类"> <!-- 右侧按钮 - 添加文章 - 具名插槽 --><template #extra><el-button @click="onAddChannel">添加分类</el-button></template><!-- 主体部分--表格 --><el-table :data="channelList" style="width: 100%" v-loading="loading"><el-table-column   label="序号"    type="index"  width="100" ></el-table-column><el-table-column   label="分类名称" prop="cate_name" ></el-table-column><el-table-column   label="分类别名" prop="cate_alias" ></el-table-column><el-table-column   label="操作"      width="100"><template #default="{row,$index}"><el-button  @click="onEditChannel(row,$index)" plain :icon="Edit" circle type="primary" ></el-button><el-button  @click="onDelChannel(row,$index)" plain :icon="Delete" circle type="danger" ></el-button></template></el-table-column><!-- 没有数据 --><template #empty><el-empty description="暂无数据"></el-empty></template></el-table><!-- 添加分类弹窗 --><channel-edit ref="dialog"> </channel-edit></page-container></div>
</template><style lang="scss" scoped>
</style>

预览视图

请添加图片描述

准备弹层表单

  1. 准备数据 和 校验规则
const formModel = ref({cate_name: '',cate_alias: ''
})
const rules = {cate_name: [{ required: true, message: '请输入分类名称', trigger: 'blur' },{pattern: /^\S{1,10}$/,message: '分类名必须是1-10位的非空字符',trigger: 'blur'}],cate_alias: [{ required: true, message: '请输入分类别名', trigger: 'blur' },{pattern: /^[a-zA-Z0-9]{1,15}$/,message: '分类别名必须是1-15位的字母数字',trigger: 'blur'}]
}
  1. 准备表单
<el-form:model="formModel":rules="rules"label-width="100px"style="padding-right: 30px"
><el-form-item label="分类名称" prop="cate_name"><el-inputv-model="formModel.cate_name"minlength="1"maxlength="10"></el-input></el-form-item><el-form-item label="分类别名" prop="cate_alias"><el-inputv-model="formModel.cate_alias"minlength="1"maxlength="15"></el-input></el-form-item>
</el-form>
  1. 编辑需要回显,表单数据需要初始化
const open = async (row) => {dialogVisible.value = trueformModel.value = { ...row }//不回显的话,需要修改为// formModel.value = {...row.row} 即可
}
  1. 基于传过来的表单数据,进行标题控制,有 id 的是编辑
:title="formModel.id ? '编辑分类' : '添加分类'"

确认提交

  1. api/article.js 封装请求 API
// 添加文章分类
export const artAddChannelService = (data) => request.post('/my/cate/add', data)
// 编辑文章分类
export const artEditChannelService = (data) =>request.put('/my/cate/info', data)
  1. 页面中校验,判断,提交请求
<el-form ref="formRef">
const formRef = ref()
const onSubmit = async () => {await formRef.value.validate()formModel.value.id? await artEditChannelService(formModel.value): await artAddChannelService(formModel.value)ElMessage({type: 'success',message: formModel.value.id ? '编辑成功' : '添加成功'})dialogVisible.value = false
}
  1. 通知父组件进行回显
const emit = defineEmits(['success'])const onSubmit = async () => {...emit('success')
}
  1. 父组件监听 success 事件,进行调用回显
<channel-edit ref="dialog" @success="onSuccess"></channel-edit>const onSuccess = () => {getChannelList()
}

源码

ChannelEdit.vue

<script setup>
import {ref} from 'vue'const dialogVisible = ref(false) //弹层状态// 组件对外暴露一个方法,open ,基于open 传来的参数,区分添加还是编辑
// open ({}) => 表单无需渲染,说明是添加分
// open ({id, name}) => 表单需要渲染,说明是编辑分类
// open调用后,可以打开弹窗
const open = async (row) =>{// console.log(row)dialogVisible.value = trueformModel.value = {...row.row} //添加 =》 重置了表单内容,编辑-> 存储了需要回显的数据
console.log('formModel:',formModel.value)
console.log(formModel.value.row.cate_name)}// 向外暴露一个方法,close,关闭弹窗
defineExpose({open
})const formModel = ref({cate_name:'',cate_alias:'' //别名
})// 表单校验规则
const rules ={cate_name:[{required:true,message:'请输入分类名称',trigger:'blur'},{pattern:/^\S{1,10}$/,message:'分类名称长度在1-10个字符之间',trigger:'blur'}],cate_alias:[{required:true,message:'请输入分类别名',trigger:'blur'},{pattern:/^[a-zA-Z0-9]{1,15}$/,message:'分类名称长度在1-15个字母或数字之间',trigger:'blur'}]}// 表单提交
import { artEditChannelService,artAddChannelService } from '@/api/article'
// import { ElMessage } from 'element-plus';
const formRef = ref()
const emit = defineEmits(['success'])
const onSubmit = async () => {await formRef.value.validate()const isEdit = formModel.value.idif(isEdit){// 编辑await artEditChannelService(formModel.value)ElMessage.success('编辑成功') }else {// 添加await artAddChannelService(formModel.value)ElMessage.success('添加成功')}// 无论编辑成功还是添加成功都需要关闭弹窗dialogVisible.value = falseemit('success',isEdit) // 触发父组件的success事件}
</script><template><el-dialog v-model="dialogVisible":title="formModel.id ? '编辑分类' : '添加分类'"width="500":before-close="handleClose"><!-- 渲染表单 --><el-form   ref="formRef" :model="formModel" :rules="rules" label-width="100px" style="padding-right:30px ;"><el-form-item label="分类名称" prop="cate_name" ><el-input v-model="formModel.cate_name" placeholder="请输入分类名称"></el-input></el-form-item><el-form-item label="分类别名" prop="cate_alias" ><el-input v-model="formModel.cate_alias" placeholder="请输入分类别名"></el-input></el-form-item></el-form><template #footer><div class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="onSubmit"> 确认 </el-button></div></template></el-dialog>
</template>

ArticleChannel.vue

<script setup>
import { artGetChannelsService } from '@/api/article'
import { Delete,Edit } from   '@element-plus/icons-vue'import {ref} from 'vue'
import ChannelEdit from './components/ChannelEdit.vue'
const channelList = ref([]) // 文章分类列表
const loading = ref(false) //加载状态const dialog = ref()
// 获取文章分类列表
const getChannelList = async () => {// 发请求之前先将loading设置为trueloading.value = true// 调用接口const res = await artGetChannelsService()channelList.value = res.data.data// channelList.value = []// 发完请求,关闭loadingloading.value = false// console.log('文章分类列表',channelList.value);}// 调用获取文章分类列表
getChannelList()// 编辑文章分类
const onEditChannel =(row) =>{
// console.log(row,$index)
dialog.value.open({row})
}       // 删除文章分类
const onDelChannel =(row,$index)=>{console.log(row,$index)}
const onAddChannel = () => {dialog.value.open({})
}const onSuccess =()=>{// 刷新文章分类列表getChannelList()
}</script><template><div><!-- 按需引入 --><page-container title="文章分类"> <!-- 右侧按钮 - 添加文章 - 具名插槽 --><template #extra><el-button @click="onAddChannel">添加分类</el-button></template><!-- 主体部分--表格 --><el-table :data="channelList" style="width: 100%" v-loading="loading"><el-table-column   label="序号"    type="index"  width="100" ></el-table-column><el-table-column   label="分类名称" prop="cate_name" ></el-table-column><el-table-column   label="分类别名" prop="cate_alias" ></el-table-column><el-table-column   label="操作"      width="100"><template #default="{row,$index}"><el-button  @click="onEditChannel(row,$index)" plain :icon="Edit" circle type="primary" ></el-button><el-button  @click="onDelChannel(row,$index)" plain :icon="Delete" circle type="danger" ></el-button></template></el-table-column><!-- 没有数据 --><template #empty><el-empty description="暂无数据"></el-empty></template></el-table><!-- 添加分类弹窗 --><channel-edit ref="dialog" @success="onSuccess"> </channel-edit></page-container></div>
</template><style lang="scss" scoped>
</style>

预览视图
请添加图片描述

文章分类删除

  1. api/article.js封装接口 api
// 删除文章分类
export const artDelChannelService = (id) =>request.delete('/my/cate/del', {params: { id }})
  1. 页面中添加确认框,调用接口进行提示(ArticleChannel.vue)
const onDelChannel = async (row) => {await ElMessageBox.confirm('你确认删除该分类信息吗?', '温馨提示', {type: 'warning',confirmButtonText: '确认',cancelButtonText: '取消'})await artDelChannelService(row.id)ElMessage({ type: 'success', message: '删除成功' })getChannelList()
}

预览视图

请添加图片描述
文章分类模块完结,撒花儿~~***

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【React】组件通信

1. 组件通信 组件间的数据传递 1.1 父传子 步骤&#xff1a; 父组件传递数据——在子组件标签上绑定属性子组件接收数据——子组件通过props参数接收数据 function Son(props) {return <div>{props.value}</div> }function App() {const value 父组件传给子…

从零开学C++:二叉搜索树

引言&#xff1a;在本篇博客当中&#xff0c;我们会将关于二叉树的进阶结构——二叉搜索树&#xff0c;强大的搜索效率让它在数据结构当中变得十分重要&#xff0c;让我们一起来进行学习吧&#xff01; 更多有关C的知识详解可前往个人主页&#xff1a;计信猫 一&#xff0c;二叉…

无人机避障——4D 毫米波雷达 SLAM篇(一)

做无人机避障相关工作&#xff0c;3D毫米波避障测试顺利后&#xff0c;开始做4D毫米波雷达无人机避障遇到4D雷达点云需要进行处理的问题&#xff0c;查阅文献&#xff0c;发现以下这篇文章中的建图方法应该为后续思考的方向&#xff0c;特此将这个开源项目进行复现和学习&#…

《论分布式存储系统架构设计》写作框架,软考高级系统架构设计师

论文真题 分布式存储系统&#xff08;Distributed Storage System&#xff09;通常将数据分散存储在多台独立的设备上。传统的网络存储系统采用集中的存储服务器存放所有数据&#xff0c;存储服务器成为系统性能的瓶颈&#xff0c;也是可靠性和安全性的焦点&#xff0c;不能满…

vue3.0 + element plus 全局自定义指令:select滚动分页

需求&#xff1a;项目里面下拉框数据较多 &#xff0c;一次性请求数据&#xff0c;体验差&#xff0c;效果就是滚动进行分页。 看到这个需求的时候&#xff0c;我第一反应就是封装成自定义指令&#xff0c;这样回头用的时候&#xff0c;直接调用就可以了。 第一步 第二步&…

双十一好物清单分享?五款超值的数码好物分享!

双十一马上就来啦&#xff0c;大家是不是都等着在这个时候买点好东西呀&#xff1f;数码产品可是咱们生活里少不了的&#xff0c;能让咱们的生活更方便、更有意思。我这儿给大家挑了五款特别值的数码好东西&#xff0c;准备来跟大家分享分享&#xff01;快来看看有没有你中意的…

【JAVA基础】JAVA类的拷贝使用示例

文章目录 一、框架介绍二、性能对比三、易用性对比四、使用示例&#xff08;一&#xff09;Apache Commons BeanUtils 使用例子1、第一个例子&#xff1a;两个对象属性个数和名称一样&#xff0c;复制过程2、第二个例子&#xff1a;属性个数和名称不一样&#xff0c;复制过程 &…

UnityHub下载任意版本的Unity包

1)先打开 // 也可以采用2直接打开 2)也可以直接打开 下载存档 (unity.com) 3)关联起来UnityHub即可

Mora:多智能体框架实现通用视频生成

人工智能咨询培训老师叶梓 转载标明出处 尽管已有一些模型能够生成视频&#xff0c;但大多数模型在生成超过10秒的长视频方面存在局限。Sora模型的出现标志着视频生成能力的一个新时代&#xff0c;它不仅能够根据文本提示生成长达一分钟的详细视频&#xff0c;而且在编辑、连接…

【CSS】定位

static ( 默认 )relative ( 相对定位 )absolute ( 绝对定位 )fixed ( 固定定位 )sticky ( 粘性定位 ) 普通文档流&#xff1f;浮动也会让元素脱离文档流&#xff0c;如果不设置浮动所有元素都处于普通文档流中。普通文档流中元素框的位置由元素在HTML中的位置决定&#xff0c;块…

Redisson分布式锁的概念和使用

Redisson分布式锁的概念和使用 一 简介1.1 什么是分布式锁&#xff1f;1.2 Redisson分布式锁的原理1.3 Redisson分布式锁的优势1.4 Redisson分布式锁的应用场景 二 案例2.1 锁竞争案例2.2 看门狗案例2.3 参考文章 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff…

文献阅读——基于拉格朗日乘子的电力系统安全域边界通用搜索方法

摘要 为提升电力系统安全域(security region&#xff0c;SR)的构建效 率&#xff0c;提出一种基于拉格朗日乘子(Lagrange multiplier&#xff0c;LM) 的电力系统安全域边界(security region boundary&#xff0c;SRB)通用搜索方法。 首先&#xff0c;根据电力系统静态安全性问…

2024.9.25 数据分析学习

资料&#xff1a; 【开课吧哩堂】数据挖掘项目之用户流失预警系统_哔哩哔哩_bilibili 五万字 | Spark吐血整理&#xff0c;学习与面试收藏这篇就够了&#xff01;-腾讯云开发者社区-腾讯云 (tencent.com) 黑马程序员Spark全套视频教程&#xff0c;4天spark3.2快速入门到精通…

文件上传漏洞+CTF实例

解题思路 前端绕过 手动修改前端js代码进行绕过&#xff1a;右击-查看页面源代码-ctff进行位置定位-修改JavaScript函数 后端绕过 文件类型绕过&#xff08;Content-Type&#xff09; 常见MIME类型描述application/octet-stream 表示所有其他情况的默认值 text/plain表示文…

啥?Bing搜索古早BUG至今未改?

首先&#xff0c;大家先看下面的一个数学公式。 Γ ( z ) ∫ 0 ∞ t z − 1 e − t d t . \Gamma(z) \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)∫0∞​tz−1e−tdt. 看不懂&#xff1f;没关系&#xff0c;因为我也看不懂 这不是谈论的重点。 当你把鼠标光标移到公式的最开头&…

小程序-生命周期与WXS脚本

生命周期 什么是生命周期 生命周期&#xff08;Life Cycle&#xff09;是指一个对象从创建 -> 运行 -> 销毁的整个阶段&#xff0c;强调的是一个时间段。 我们可以把每个小程序运行的过程&#xff0c;也概括为生命周期&#xff1a; 小程序的启动&#xff0c;表示生命…

Github 2024-09-23 开源项目周报 Top15

根据Github Trendings的统计,本周(2024-09-23统计)共有15个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6C++项目3C项目3HTML项目2PowerShell项目1TypeScript项目1JavaScript项目1Blade项目1PHP项目1Bootstrap 5: Web上开发响应式、移动优…

Kafka 面试题

参考&#xff1a; https://javabetter.cn/interview/kafka-40.htmlhttps://javaguide.cn/high-performance/message-queue/kafka-questions-01.html Kafka 架构 名词概念 Producer&#xff08;生产者&#xff09; : 产生消息的一方。 Consumer&#xff08;消费者&#xff09; …

影刀---实现我的第一个抓取数据的机器人

你们要的csdn自动回复机器人在这里文末哦&#xff01; 这个上传的资源要vip下载&#xff0c;如果想了解影刀这个软件的话可以私聊我&#xff0c;我发你 目录 1.网页对象2.网页元素3.相似元素组4.元素操作设置下拉框复选框滚动条获取元素的信息 5.变量6.数据的表达字符串变量列…

数据库主备副本物理复制和逻辑复制对比

数据库主从节点的数据一致性是保证数据库高可用的基本要求&#xff0c;各个数据库在实现方式上也各有异同。而主备复制的方式无外乎两种&#xff1a;物理复制和逻辑复制&#xff0c;本文简要对比下两种方式的不同&#xff0c;并分析下国产数据库是如何实现的。 1、数据库复制基…