温锦文欧普厨电及净水器总代理 发表于 2024-12-31 06:23:18

自研国产零依赖前端UI框架实战007 封装编辑和删除相关的功能组件

媒介

前面我们已经实现了一个表格, 能够展示用户的信息, 一个分页能够执行分页获取用户信息.
到目前为止, 数据的渲染, 我们基本就做的差不多了, 接下来我们来扩展一下表格, 让其支持添加按钮, 我们在内里添加编辑按钮和删除按钮.
表格样式调整

我调整了一下表格的样式, 增加了操作列, 目前看起来是如许的:
https://i-blog.csdnimg.cn/direct/d238b48f779949cd8b5c870a121253f3.png
代码内里增加了操作这一列:
https://i-blog.csdnimg.cn/direct/5f577a54ea2d497ebeb8b7ff375852f2.png
操作这一列可以根据一个叫做operator的属性进行控制, 默认是true, 如果改成false, 则不表现操作列.
稍微调整一下删除按钮的样式

https://i-blog.csdnimg.cn/direct/6940b4715e2e407faadc158557b21593.png
暴露按钮点击方法

起首是在组件中添加要暴露的方法:
const emit = defineEmits(['edit', 'delete']);
const onEdit = (index, item) => emit('edit', index, item) // 编辑
const onDelete = (index, item) => emit('delete', index, item) // 删除
接着给按钮绑定:
<button @click.stop="onEdit(k, v)">编辑</button>
<button class="delete" @click.stop="onDelete(k,v)">删除</button>
在App.vue中监听编辑和删除这两个事件:
<zdp_table1
      :columns="columns"
      :data="data"
      @edit="onEdit"
      @delete="onDelete"
    />
再简单的实现事件的监听:
const onEdit = (index, item) => {
console.log("编辑", index, item)
}
const onDelete = (index, item) => {
console.log("删除", index, item)
}
此时, 当我们点击编辑按钮的删除按钮的时间, 控制台会输出对应的内容.
https://i-blog.csdnimg.cn/direct/90297f3e9a444c63bd7c42331f5db091.png
此时页面结果如下:
https://i-blog.csdnimg.cn/direct/38493233e5254016b743be45e451578c.png
App.vue的完备代码如下:
<script setup>import zdp_table1 from "./zdpui/components/zdp_table1.vue";import zdp_page1 from "./zdpui/components/zdp_page1.vue";import random from "./zdpui/js/random.js";import {ref} from "vue";const columns = [{    title: "员工编号",    key: "id",    width: 80,    align: "center"},{    title: "姓名",    key: "name",    width: 100,    align: "center"},{    title: "年龄",    key: "age",    width: 100,    align: "center"}]const page = ref(1);const size = ref(10);const total = ref(100);const data = ref(random.users(size.value))const onChangePage = (v) => {page.value = vconst newData = random.getPageUser(      page.value,      size.value,)data.value = newData.datatotal.value = total.value}const onEdit = (index, item) => {
console.log("编辑", index, item)
}
const onDelete = (index, item) => {
console.log("删除", index, item)
}
</script><template><div>    <zdp_table1
      :columns="columns"
      :data="data"
      @edit="onEdit"
      @delete="onDelete"
    />
    <zdp_page1      :page="page"      :size="size"      :total="total"      @change="onChangePage"    /></div></template> 删除确认

当我们点击删除的时间, 盼望能够弹出一个确认删除的对话框, 好比像下面如许.
https://i-blog.csdnimg.cn/direct/f9e7c255f16d4bd18d795d0ab5690adc.png
这个我已经封装好了, 比想象中要简单的多, 完备代码如下:
<script setup>
import {defineEmits, defineProps} from 'vue';

const props = defineProps({
show: {
    type: Boolean,
    default: false
},
title: {
    type: String,
    default: '确认删除'
},
content: {
    type: String,
    default: '你确定要删除该项目吗?此操作不可逆。'
},
ok: {
    type: String,
    default: '确认'
},
cancel: {
    type: String,
    default: '取消'
}
});

const emit = defineEmits(['confirm', 'close']);
const onClose = () => emit('close')
const onConfirm = () => emit('confirm')
</script>

<template>
<div class="confirm-delete-dialog" v-if="props.show">
    <div class="dialog-overlay" @click.self="onClose"></div>
    <div class="dialog-content">
      <h2>{{ props.title }}</h2>
      <p>{{ props.content }}</p>
      <div class="dialog-buttons">
      <button @click="onConfirm">{{ props.ok }}</button>
      <button @click="onClose">{{ props.cancel }}</button>
      </div>
    </div>
</div>
</template>


<style scoped>
.confirm-delete-dialog {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}

.dialog-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}

.dialog-content {
background-color: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
z-index: 1001;
text-align: center;
}

.dialog-content h2 {
margin-top: 0;
color: #009FFF;
}

.dialog-content p {
margin-bottom: 20px;
}

.dialog-buttons button {
padding: 10px 20px;
margin: 0 10px;
border: none;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
color: white;
transition: all 0.3s ease-in-out;
}

.dialog-buttons button:first-child {
background: linear-gradient(45deg, #C70039, #FF5733);
box-shadow: 0 5px 10px rgba(199, 0, 57, 0.4);
}

.dialog-buttons button:first-child:hover {
transform: translateY(-3px);
box-shadow: 0 8px 15px rgba(199, 0, 57, 0.6);
background: linear-gradient(45deg, #FF5733, #FF8C00);
}

.dialog-buttons button:first-child:active {
transform: translateY(1px);
box-shadow: 0 3px 8px rgba(199, 0, 57, 0.8);
background: linear-gradient(45deg, #900C3F, #C70039);
}

.dialog-buttons button:last-child {
background: linear-gradient(45deg, #009FFF, #0066CC);
box-shadow: 0 5px 10px rgba(0, 159, 255, 0.4);
}

.dialog-buttons button:last-child:hover {
transform: translateY(-3px);
box-shadow: 0 8px 15px rgba(0, 159, 255, 0.6);
background: linear-gradient(45deg, #00BFFF, #0088EE);
}

.dialog-buttons button:last-child:active {
transform: translateY(1px);
box-shadow: 0 3px 10px rgba(0, 159, 255, 0.8);
background: linear-gradient(45deg, #0077DD, #0055AA);
}
</style>
在App.vue中的利用代码如下:
https://i-blog.csdnimg.cn/direct/cb1e4e33862c4bfeb6d4c7c3c1da4a60.png
编辑弹窗

结果预览:
https://i-blog.csdnimg.cn/direct/6346a17aec03432e9ea0c3477bc00d8d.png
此时App.vue代码如下:
<script setup>import zdp_table1 from "./zdpui/components/zdp_table1.vue";import zdp_page1 from "./zdpui/components/zdp_page1.vue";import random from "./zdpui/js/random.js";import {ref} from "vue";import zdp_confirm1 from "./zdpui/components/zdp_confirm1.vue";import zdp_modal1 from "./zdpui/components/zdp_modal1.vue";import Zdp_input1 from "./zdpui/components/zdp_input1.vue";const columns = [{    title: "员工编号",    key: "id",    width: 80,    align: "center"},{    title: "姓名",    key: "name",    width: 100,    align: "center"},{    title: "年龄",    key: "age",    width: 100,    align: "center"}]const page = ref(1);const size = ref(10);const total = ref(100);const data = ref(random.users(size.value))const onChangePage = (v) => {page.value = vconst newData = random.getPageUser(      page.value,      size.value,)data.value = newData.datatotal.value = total.value}const onEdit = (index, item) => {console.log("编辑", index, item)showEditDialog.value = true;}const onDelete = (index, item) => {console.log("删除", index, item)showDeleteDialog.value = true;}const showDeleteDialog = ref(false);const onConfirmDelete = () => {console.log("确认删除");showDeleteDialog.value = false;};const onCloseDeleteDialog = () => {console.log("取消删除");showDeleteDialog.value = false;};const showEditDialog = ref(false);const formData = ref({name: "张三", age: 23});const handleEditConfirm = (userData) => {console.log('确认编辑操作,用户数据:', userData);// 在这里添加编辑逻辑,如发送编辑请求等};const handleCloseDialog = () => {showEditDialog.value = false;};</script><template><div>    <zdp_table1
      :columns="columns"
      :data="data"
      @edit="onEdit"
      @delete="onDelete"
    />
    <zdp_page1      :page="page"      :size="size"      :total="total"      @change="onChangePage"    />    <zdp_confirm1      :show="showDeleteDialog"      @confirm="onConfirmDelete"      @close="onCloseDeleteDialog"    />    <zdp_modal1      :show="showEditDialog"      @confirm="handleEditConfirm"      @close="handleCloseDialog"    >      <zdp_input1          label="姓名"          v-model="formData.name"          placeholder="请输入姓名"      />      <zdp_input1          label="年龄"          v-model="formData.age"          placeholder="请输入年龄"      />    </zdp_modal1></div></template> 继续封装按钮

到这一步的时间, 发现按钮有很多地方都是一样的, 重复的, 以是决定对按钮进行封装.
按钮组件的内容如下:
<script setup>
import {defineProps, defineEmits} from 'vue';

const props = defineProps({
text: {
    type: String,
    default: '按钮',
},
type: {
    type: String,
    // primary,danger
    default: 'primary',
}
})
const emits = defineEmits(['click'])
</script>

<template>
<button
      @click="emits('click')"
      :class="props.type"
>
    {{ props.text }}
</button>
</template>

<style scoped>
button {
padding: 10px 20px;
margin: 0 10px;
border: none;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
color: white;
transition: all 0.3s ease-in-out;
}

button.danger {
background: linear-gradient(45deg, #C70039, #FF5733);
box-shadow: 0 5px 10px rgba(199, 0, 57, 0.4);
}

button.danger:hover {
transform: translateY(-3px);
box-shadow: 0 8px 15px rgba(199, 0, 57, 0.6);
background: linear-gradient(45deg, #FF5733, #FF8C00);
}

button.danger:active {
transform: translateY(1px);
box-shadow: 0 3px 8px rgba(199, 0, 57, 0.8);
background: linear-gradient(45deg, #900C3F, #C70039);
}

button.primary {
background: linear-gradient(45deg, #009FFF, #0066CC);
box-shadow: 0 5px 10px rgba(0, 159, 255, 0.4);
}

button.primary:hover {
transform: translateY(-3px);
box-shadow: 0 8px 15px rgba(0, 159, 255, 0.6);
background: linear-gradient(45deg, #00BFFF, #0088EE);
}

button.primary:active {
transform: translateY(1px);
box-shadow: 0 3px 10px rgba(0, 159, 255, 0.8);
background: linear-gradient(45deg, #0077DD, #0055AA);
}
</style>
利用方法如下:
<zdp_button1/>
<zdp_button1 type="danger"/>
在界面中的表现结果如下:
外链图片转存失败,源站大概有防盗链机制,建议将图片保存下来直接上传
总结

现在, 我们已经有了自己的按钮组件, 确认框组件, 编辑表单组件, 组件越来越多了.
不外这个时间, 组件之间的拆分, 组合也变得越来越复杂了, 好比这个编辑表单组件, 就因为有输入框组件, 按钮组件, 确认框组件等多个组件的组合, 显得很复杂, 样式调整稍微贫苦了一点点.
不外一切都还比较顺利!!!
继续做吧!!!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 自研国产零依赖前端UI框架实战007 封装编辑和删除相关的功能组件