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>

使用结果

vue3动态加载对话框的方法实例

vue3动态加载对话框的方法实例

动态操作对话框的实现

动态操作对话框,主要思路是动态创建虚拟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,加载,对话框
0
投稿

猜你喜欢

  • Python Flask框架实现简单加法工具过程解析

    2021-08-17 20:36:11
  • python3 requests中使用ip代理池随机生成ip的实例

    2022-11-19 21:52:04
  • python安装教程 Pycharm安装详细教程

    2022-08-08 02:25:55
  • python 数据挖掘算法的过程详解

    2022-11-17 09:09:19
  • Python实现RSA加密解密

    2022-04-22 19:07:41
  • Ubuntu手动安装mysql5.7.10

    2024-01-16 11:53:56
  • 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
  • 阿里系的中国雅虎新首页浅谈

    2008-07-16 12:19:00
  • 在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
  • 详解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
  • 深入理解Python虚拟机中列表(list)的实现原理及源码剖析

    2022-07-10 22:02:27
  • Pandas时间序列重采样(resample)方法中closed、label的作用详解

    2023-01-31 17:46:36
  • Python实现贪吃蛇小游戏(双人模式)

    2021-06-07 11:15:02
  • asp之家 网络编程 m.aspxhome.com