前言
el-dialog 是 Element UI 框架中的一个常用组件,用于实现弹窗对话框的展示和交互。它提供了丰富的功能和配置选项,可以满足不同场景下的需求。本文将深入探讨 el-dialog的源码
基本使用
组件使用
<el-button @click="showDialog">打开对话框</el-button>
<my-dialog :visible.sync="visible" title="弹框" center>
<el-input ></el-input>
<div>弹框内容</div>
<div slot="footer">
<el-button>确定</el-button>
<el-button @click="visible = false">取消</el-button>
</div>
</my-dialog>
源码
思路
- 弹框组件一开始是隐藏,打开弹框的同时会显示弹框内容,增加遮罩层,层级比弹框低
- 遮罩层也可以插入到body里面,只需将modalAppendToBody:true
- 弹框内容默认在当前页面,如果设置appendToBody:true,将会把弹框元素插入到body
- 关闭弹框时,去掉遮罩层,同时通过v-show隐藏弹框元素
实现代码
<template>
<div
v-show="visible"
class="el-dialog__wrapper"
@click.self="handleWrapperClick"
>
<div :key="key" class="el-dialog" ref="dialog" :style="style">
<div class="el-dialog__header">
<slot name="title">
<span class="el-dialog__title">{{ title }}</span>
</slot>
</div>
<div class="el-dialog__body" v-if="rendered"><slot></slot></div>
<div class="el-dialog__footer" v-if="$slots.footer">
<slot name="footer"></slot>
</div>
</div>
</div>
</template>
<script>
let idSeed = 1;
let modalDom = null;
export default {
props: {
title: {
type: String,
default: "",
},
modalAppendToBody: {
type: Boolean,
default: false,
},
appendToBody: {
type: Boolean,
default: false,
},
closeOnClickModal: {
type: Boolean,
default: true,
},
width: String,
visible: Boolean,
top: {
type: String,
default: "15vh",
},
},
data() {
return {
key: 0,
opened: false,
rendered: false,
zIndex: 2000,
};
},
computed: {
style() {
let style = {};
style.marginTop = this.top;
if (this.width) {
style.width = this.width;
}
return style;
},
},
watch: {
visible(val) {
if (val) {
this.rendered = true;
this.open();
if (this.appendToBody) {
document.body.appendChild(this.$el);
}
} else {
this.close();
}
},
},
methods: {
// 点击遮罩层,关闭
handleWrapperClick() {
if (!this.closeOnClickModal) return;
this.handleClose();
},
// 关闭弹框
handleClose() {
this.$emit("update:visible", false);
},
// 插入遮罩层
open() {
if (this.opened) return;
this._opening = true;
const dom = this.$el;
if (this._closing) {
this.closeModal(this._popupId);
this._closing = false;
}
// 增加遮罩层
this.openModal(
this._popupId,
++this.zIndex,
this.modalAppendToBody ? undefined : dom
);
// 弹框增加一个层级
dom.style.zIndex = ++this.zIndex;
this.opened = true;
this._opening = false;
},
close() {
this._closing = true;
this.opened = false;
this.closeModal(this._popupId);
this._closing = false;
},
openModal(id, zIndex, dom) {
// 创建div,注册滚动和点击事件
const modalDom = this.getModal();
modalDom.className = "v-modal";
modalDom.style.zIndex = zIndex;
modalDom.tabIndex = 0;
modalDom.style.display = "";
// 遮罩层加在页面
if (dom && dom.parentNode && dom.parentNode.nodeType !== 11) {
dom.parentNode.appendChild(modalDom);
} else {
document.body.appendChild(modalDom);
}
},
closeModal() {
if(!modalDom) {
return
}
if (modalDom.parentNode) modalDom.parentNode.removeChild(modalDom);
modalDom.style.display = "none";
modalDom = undefined;
},
getModal() {
if (!modalDom) {
modalDom = document.createElement("div");
modalDom.addEventListener("click", () => {
if (this.closeOnClickModal) {
this.close();
}
});
}
return modalDom;
},
},
mounted() {
// 一开始渲染弹框
if (this.visible) {
this.rendered = true;
this.open();
if (this.appendToBody) {
document.body.appendChild(this.$el);
}
}
},
beforeMount() {
this._popupId = "popup-" + idSeed++;
},
beforeDestroy() {
this.closeModal(this._popupId); // 关闭弹框
modalDom = null;
},
};
</script>
最后
在本文中,我们深入了解了 el-dialog 组件的使用方法。通过灵活地使用 el-dialog 组件,我们可以实现各种各样的弹窗对话框,并满足不同场景下的需求。希望本文能够帮助你更好地理解和使用 el-dialog 组件,实现代码根据源代码改造!