vue3動(dòng)態(tài)加載對(duì)話框的方法實(shí)例
簡(jiǎn)介
介紹使用vue3的異步組件動(dòng)態(tài)管理對(duì)話框組件,簡(jiǎn)化對(duì)話框組件使用方式。本文使用的是vue3、typescript、element_plus完成的示例。
常規(guī)方式使用對(duì)話框
一般情況下,使用對(duì)話框組件,會(huì)使用v-model進(jìn)行雙向綁定,通過(guò)visible變量控制對(duì)話框的顯示和關(guān)閉。常規(guī)方式有一個(gè)弊端,自定義組件中使用<el-dialog>,需要通過(guò)父組件控制自定義組件是否展示。
<template>
<ElButton type="primary" @click="openGeneral()">常規(guī)方式打開(kāi)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>異步動(dòng)態(tài)加載
先看使用異步組件進(jìn)行動(dòng)態(tài)加載對(duì)話框的方式。異步組件使用到的是defineAsyncComponent接口,只有使用到這個(gè)組件,才會(huì)從網(wǎng)絡(luò)上加載。動(dòng)態(tài)操作使用的useDzModal
使用方式
<template> <ElButton type="primary" @click="openTestModalAsync()">動(dòng)態(tài)異步打開(kāi)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()
// # 通過(guò)dzmodal動(dòng)態(tài)操作對(duì)話框
const openTestModalAsync=()=>{
dzmodal.open(TestModalAsync,{
name:'張三'
})
.then(res=>{
if(res.type==='ok'){
ElMessageBox.alert('TestModal點(diǎn)擊了確定');
}else{
ElMessageBox.alert('TestModal點(diǎn)擊了取消');
}
})
}
</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>通過(guò)DzModal打開(kāi)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>使用結(jié)果


動(dòng)態(tài)操作對(duì)話框的實(shí)現(xiàn)
動(dòng)態(tài)操作對(duì)話框,主要思路是動(dòng)態(tài)創(chuàng)建虛擬dom節(jié)點(diǎn),將對(duì)話框組件渲染到組件上,核心關(guān)鍵點(diǎn)是要?jiǎng)討B(tài)創(chuàng)建的節(jié)點(diǎn)的上下文為當(dāng)前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)=>{
// 彈出框關(guān)閉時(shí)移除節(jié)點(diǎn)
document.body.removeChild(container)
reslove(this.ok(data));
},
onCancel:(data?:any)=>{
reslove(this.cancel(data));
}
});
// 這里很重要,關(guān)聯(lián)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')總結(jié)
使用異步動(dòng)態(tài)加載對(duì)話框,父組件無(wú)需控制對(duì)話框組件的visible屬性 , 這樣可以簡(jiǎn)化父組件操作,不在關(guān)心對(duì)話框組件在什么時(shí)間關(guān)閉,如果對(duì)話框組件需要訪問(wèn)網(wǎng)絡(luò),也在子組件中完成。父組件主要做兩件事:
- 通過(guò)異步組件方式引入對(duì)話框組件
- 打開(kāi)對(duì)話框組件
到此這篇關(guān)于vue3動(dòng)態(tài)加載對(duì)話框的文章就介紹到這了,更多相關(guān)vue3動(dòng)態(tài)加載對(duì)話框內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue實(shí)現(xiàn)簡(jiǎn)單購(gòu)物車小案例
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)簡(jiǎn)單購(gòu)物車小案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
vue實(shí)現(xiàn)超過(guò)兩行顯示展開(kāi)收起的代碼
這篇文章主要介紹了vue實(shí)現(xiàn)超過(guò)兩行顯示展開(kāi)收起的代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
vue.js實(shí)現(xiàn)只能輸入數(shù)字的輸入框
這篇文章主要為大家詳細(xì)介紹了vue.js實(shí)現(xiàn)只能輸入數(shù)字的輸入框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
Vue3中集成高德地圖并實(shí)現(xiàn)平移縮放功能
隨著前端技術(shù)的不斷發(fā)展,地圖應(yīng)用在我們的項(xiàng)目中越來(lái)越常見(jiàn),本文將介紹如何在Vue3項(xiàng)目中集成高德地圖,并通過(guò)簡(jiǎn)單的配置實(shí)現(xiàn)地圖的平移和縮放功能,需要的朋友可以參考下2024-09-09
Vue的route-view子頁(yè)面調(diào)用父頁(yè)面的函數(shù)詳解
這篇文章主要介紹了Vue的route-view子頁(yè)面調(diào)用父頁(yè)面的函數(shù)詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
vue.js表單驗(yàn)證插件(vee-validate)的使用教程詳解
這篇文章主要介紹了vue.js表單驗(yàn)證插件(vee-validate)的使用,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05

