vue3动态加载对话框的方法实例
作者:程序员德子 时间:2024-05-09 15:16:55
简介
介绍使用vue3的异步组件动态管理对话框组件,简化对话框组件使用方式。本文使用的是vue3、typescript、element_plus完成的示例。
常规方式使用对话框
一般情况下,使用对话框组件,会使用v-model进行双向绑定,通过visible变量控制对话框的显示和关闭。常规方式有一个弊端,自定义组件中使用<el-dialog>,需要通过父组件控制自定义组件是否展示。
<template>
<ElButton type="primary" @click="openGeneral()">常规方式打开Modal</ElButton>
<el-dialog
v-model="dialogVisible"
title="Tips"
width="30%"
:before-close="handleClose"
>
<span>This is a message</span>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">Cancel</el-button>
<el-button type="primary" @click="dialogVisible = false"
>Confirm</el-button
>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
import {ref } from 'vue';
const dialogVisible = ref(false)
const openGeneral=()=>{
dialogVisible.value=true
}
</script>
异步动态加载
先看使用异步组件进行动态加载对话框的方式。异步组件使用到的是defineAsyncComponent接口,只有使用到这个组件,才会从网络上加载。动态操作使用的useDzModal
使用方式
<template>
<ElButton type="primary" @click="openTestModalAsync()">动态异步打开TestModal</ElButton>
</template>
<script setup lang="ts">
import { defineAsyncComponent,ref } from 'vue';
import { ElMessageBox } from 'element-plus';
import { useDzModal } from './dzmodal'
// 异步加载组件
const TestModalAsync = defineAsyncComponent(()=>import('./components/TestModal.vue'))
const dzmodal = useDzModal()
// # 通过dzmodal动态操作对话框
const openTestModalAsync=()=>{
dzmodal.open(TestModalAsync,{
name:'张三'
})
.then(res=>{
if(res.type==='ok'){
ElMessageBox.alert('TestModal点击了确定');
}else{
ElMessageBox.alert('TestModal点击了取消');
}
})
}
</script>
TestModal.vue
<script setup lang="ts">
import { reactive, ref, defineProps } from 'vue'
const emits = defineEmits(['ok','cancel'])
const props = defineProps({
name: String
});
const dialogVisible = ref(true)
const resultData= reactive({
type:'ok',
data:{}
})
</script>
<template>
<el-dialog
v-model="dialogVisible"
title="TestModal"
width="30%"
>
<div>通过DzModal打开TestModal</div>
<div>外部传入:{{ name }}</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="emits('cancel',{});dialogVisible = false">Cancel</el-button>
<el-button type="primary" @click="emits('ok',{});dialogVisible = false"
>Confirm</el-button
>
</span>
</template>
</el-dialog>
</template>
<style scoped>
</style>
使用结果
动态操作对话框的实现
动态操作对话框,主要思路是动态创建虚拟dom节点,将对话框组件渲染到组件上,核心关键点是要动态创建的节点的上下文为当前app上下文vm.appContext = this._app._context
DzModalService.ts
import { App, inject, Plugin, h, render} from 'vue'
import { ComponentOptions } from 'vue';
export const DzModalSymbol = Symbol()
export class DzModalResult{
type: 'ok'|'cancel'|'string' = 'ok'
body?:any= undefined
}
export class DzModalService{
private _app?:App=undefined
constructor(app:App){
this._app=app;
}
public open(modal:ComponentOptions, props?: any):Promise<DzModalResult>{
return new Promise((reslove,reject)=>{
if(!this._app){
reject('_app is undefined')
return;
}
const container = document.createElement("div");
document.body.appendChild(container)
// 这里需要合并props,传入到组件modal
const vm = h(modal, {
...props,
onOk:(data?:any)=>{
// 弹出框关闭时移除节点
document.body.removeChild(container)
reslove(this.ok(data));
},
onCancel:(data?:any)=>{
reslove(this.cancel(data));
}
});
// 这里很重要,关联app上下文
vm.appContext = this._app._context
render(vm,container);
});
}
public ok(data?:any):DzModalResult{
const result = new DzModalResult();
result.type='ok';
result.body=data;
return result;
}
public cancel(data?:any):DzModalResult{
const result = new DzModalResult();
result.type='cancel';
result.body=data;
return result;
}
}
export function useDzModal(): DzModalService {
const dzModal = inject<DzModalService>(DzModalSymbol)
if(!dzModal){
throw new Error('No DzModal provided!')
}
return dzModal;
}
const plugin: Plugin = {
install(app:App, options?:{[key:string]:any}){
const dzModal = new DzModalService(app)
app.config.globalProperties.$dzModal= dzModal
app.provide(DzModalSymbol, dzModal)
}
}
export default plugin;
main.ts
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import DzModal from './dzmodal'
createApp(App)
.use(ElementPlus)
.use(DzModal) // 安装 dzmodal插件
.mount('#app')
通过异步组件方式引入对话框组件
打开对话框组件
来源:https://juejin.cn/post/7080287482771669028
标签:vue3,加载,对话框
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Python Flask框架实现简单加法工具过程解析
2021-08-17 20:36:11
![](https://img.aspxhome.com/file/2023/4/66864_0s.png)
python3 requests中使用ip代理池随机生成ip的实例
2022-11-19 21:52:04
python安装教程 Pycharm安装详细教程
2022-08-08 02:25:55
![](https://img.aspxhome.com/file/2023/2/68412_0s.jpg)
python 数据挖掘算法的过程详解
2022-11-17 09:09:19
![](https://img.aspxhome.com/file/2023/1/107481_0s.png)
Python实现RSA加密解密
2022-04-22 19:07:41
![](https://img.aspxhome.com/file/2023/6/103316_0s.png)
Ubuntu手动安装mysql5.7.10
2024-01-16 11:53:56
![](https://img.aspxhome.com/file/2023/2/79012_0s.jpg)
Perl使用chdir的实例代码
2023-02-13 19:33:56
python Timer 类使用介绍
2022-09-02 18:36:37
Python3.10 Generator生成器Coroutine原生协程详解
2023-10-25 15:31:36
Python 实现文件读写、坐标寻址、查找替换功能
2021-06-02 07:36:42
![](https://img.aspxhome.com/file/2023/4/127014_0s.jpg)
阿里系的中国雅虎新首页浅谈
2008-07-16 12:19:00
![](https://img.aspxhome.com/file/UploadPic/20087/16/2008716122345245s.png)
在Python中处理时间之clock()方法的使用
2021-09-22 06:07:26
django和vue互传图片并进行处理和展示
2021-04-24 20:39:16
MySQL错误Forcing close of thread的两种解决方法
2024-01-25 15:24:44
![](https://img.aspxhome.com/file/2023/8/83378_0s.jpg)
详解django的serializer序列化model几种方法
2022-12-06 00:40:08
MSSQL安全设置的具体步骤和方法小结
2012-07-11 15:54:11
JavaScript中call,apply,bind的区别与实现
2024-04-22 12:51:26
![](https://img.aspxhome.com/file/2023/1/136021_0s.png)
深入理解Python虚拟机中列表(list)的实现原理及源码剖析
2022-07-10 22:02:27
![](https://img.aspxhome.com/file/2023/3/102823_0s.png)
Pandas时间序列重采样(resample)方法中closed、label的作用详解
2023-01-31 17:46:36
Python实现贪吃蛇小游戏(双人模式)
2021-06-07 11:15:02