本专栏为了还在Vue2x的广大同胞提供一点升级3X的借鉴思路
适用人群
- Vue前端开发者
阅读条件
- 撸一遍Vue3文档
收获
- 纯净的Vue3-admin框架
如果你是一名成熟的开发工程师,可以直接访问成品
【admin-mini】函数化el-dialog弹出层
接上次封装table列表
列表想要好,表单少不了 skr~
很糟糕的一种组织代码方式
(常见于祖传骂娘项目 🤬)
<template>
<el-table>
...列表页代码
</el-table>
<el-dialog>
...新增业务表单
</el-dialog>
<el-dialog>
...编辑业务表单
</el-dialog>
<el-dialog>
...绑定业务表单
</el-dialog>
....
</template>
<script>
...列表变量数据、各种函数、业务逻辑
...新增业务 变量数据、各种函数、业务逻辑
...编辑业务 变量数据、各种函数、业务逻辑
...绑定业务 变量数据、各种函数、业务逻辑
</script>
<style>
...列表样式
...新增样式
...编辑样式
...绑定样式
</style>
正常猿类写法
这种组织代码方式也是最为常见的方式,但是随着业务逻辑的复杂
一个列表页可能包含不下10个弹出层业务逻辑
我们仍需要上下反复横跳☹️
- 维护 el-dialog 的显示与隐藏
- 给业务组件传输 props
- 维护业务组件的回调
<template>
<el-table>
...列表页代码
</el-table>
<el-dialog>
<新增业务组件 />
</el-dialog>
<el-dialog>
<编辑业务表单 />
</el-dialog>
<el-dialog>
<绑定业务表单 />
</el-dialog>
....
</template>
<script>
...列表变量数据、各种函数、业务逻辑
import 新增业务
import 编辑业务
import 绑定业务
</script>
<style>
...列表样式
</style>
遥遥领先写法 😮
<template>
<el-table>
...列表页代码
</el-table>
....
</template>
<script>
...列表变量数据、各种函数、业务逻辑
弹出('新增业务',{...props},{...回调})
弹出('编辑业务',{...props},{...回调})
弹出('绑定业务',{...props},{...回调})
</script>
<style>
...列表样式
</style>
要实现以上调用方式,首先要解决如果动态把一个vue组件插入到el-dialog
这里我们使用vue提供的渲染函数h
在index.vue中使用h把组件转成vnode 传入el-dialog的slot中
封装成一个vue插件:
import { render, h, getCurrentInstance, onBeforeUnmount } from 'vue'
import { ElDialog } from 'element-plus'
import 'element-plus/es/components/dialog/style/css'
export default function useAdminDialog() {
const vm = getCurrentInstance()
return function (vnode, opts) {
onBeforeUnmount(() => {
close()
}, vm)
vnode.appContext = vm.appContext
let dom = document.createElement('div')
let dialogVnode = h(
ElDialog,
{
onClosed: () => {
dom.remove()
},
modelValue: true,
closeOnClickModal: false,
alignCenter: true,
...opts
},
{ default: () => vnode }
)
dialogVnode.appContext = vm.appContext
let _success = vnode.props.onSuccess || function () {}
let _end = vnode.props.onEnd || function () {}
vnode.props.onSuccess = function (...arr) {
_success(...arr)
close()
}
vnode.props.onEnd = function (...arr) {
_end(...arr)
close()
}
function close() {
dialogVnode.component.props.modelValue = false
}
render(dialogVnode, dom)
document.body.appendChild(dom)
}
}
useAdminDialog.install = function (app) {
void app
// app.config.globalProperties.useAdminDialog = useAdminDialog
}
调用
<template>
<div class="admin-view">
<div class="admin-view-body">
<div class="admin-table-btns">
<el-button @click="openAdd" type="primary" icon="plus">新增</el-button>
</div>
<div class="admin-table-list">
<el-table border :data="$table.data" :empty-text="$table.emptyText" v-loading="$table.loading"
table-layout="auto">
<el-table-column prop="username" label="帐号" />
<el-table-column prop="nickName" label="用户姓名" />
<el-table-column label="操作" width="400px">
<template #default="scope">
<el-space spacer="|">
<el-link :disabled="scope.row.loading" type="primary" @click="openEdit(scope.row)">编辑</el-link>
<el-link :disabled="scope.row.loading" type="primary" @click="openDel(scope.row)">删除</el-link>
<el-link :disabled="scope.row.loading" type="primary" @click="openPassword(scope.row)">修改密码</el-link>
</el-space>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script setup>
import { userList, userDel } from '@/api'
import { h } from 'vue'
import useAdminDialog from '@/plugins/use-admin-dialog'
import useAdminTable from '@/plugins/use-admin-table'
import { ElMessage, ElMessageBox } from 'element-plus'
const adminDialog = useAdminDialog()
const $table = useAdminTable({
api: userList
})
async function openAdd() {
adminDialog(
h((await import('./post.vue')).default, {
onSuccess: () => {
$table.getTable()
}
}),
{ title: '新增' }
)
}
async function openEdit(row) {
adminDialog(
h((await import('./post.vue')).default, {
row: row,
onSuccess: () => {
$table.getTable()
}
}),
{ title: '编辑' }
)
}
async function openPassword(row) {
adminDialog(
h((await import('./change-password.vue')).default, {
row: row,
onSuccess: () => {
$table.getTable()
}
}),
{ title: '修改密码' }
)
}
function openDel(row) {
row.loading = true;
ElMessageBox.confirm("确定删除?", "提示", { type: "warning" }).then(() => {
userDel({
userId: row.userId
}).then(res => {
if (res.data.code == 0) {
$table.getTable()
} else {
ElMessage.error(res.data.msg)
}
}).finally(() => {
row.loading = false;
})
}).catch(() => { row.loading = false; })
}
</script>
<style></style>