弹窗工具类
封装初意是为了实现脱离html标签来使用的简单的弹窗
完全动态创建和销毁
不依赖模板文件
支持通过props传递数据和回调
适合作为全局弹窗组件使用
组件定义
const DialogComponent = Vue.extend({
props: ["title", "content", "onClose"],
methods: { /* 关闭逻辑 */ },
render(h) { /* 虚拟DOM结构 */ }
})
核心机制:通过
Vue.extend+render函数实现声明式弹窗模板样式方案:内联样式对象集中管理,统一采用JS对象风格写法
交互响应:同时支持遮罩层点击关闭和按钮点击关闭
服务化封装层
export function showDialog(options) {
const instance = new DialogComponent(...)
document.body.appendChild(instance.$el)
return instance
}
动态挂载:按需创建新实例并挂载到
body末尾服务式调用:导出函数实现API式调用 (
showDialog({ title:'Hi' }))
import Vue from "vue";
const DialogComponent = Vue.extend({
props: ["title", "content", "onClose"], // 已添加onClose回调prop
methods: {
close() {
if (typeof this.onClose === "function") {
this.onClose(); // 触发父组件传递的回调函数
}
this.$destroy();
this.$el.parentElement.removeChild(this.$el);
},
},
render(h) {
const styles = {
mask: {
position: "fixed",
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: "rgba(0,0,0,0.5)",
display: "flex",
justifyContent: "center",
alignItems: "center",
zIndex: 999,
},
dialog: {
backgroundColor: "white",
borderRadius: "4px",
padding: "20px",
minWidth: "300px",
boxShadow: "0 2px 12px 0 rgba(0,0,0,0.1)",
},
header: {
fontSize: "18px",
fontWeight: "bold",
marginBottom: "10px",
},
content: {
marginBottom: "15px",
},
footer: {
textAlign: "right",
},
closeBtn: {
padding: "6px 12px",
backgroundColor: "#409eff",
color: "white",
border: "none",
borderRadius: "3px",
cursor: "pointer",
},
};
return h("div", {
style: styles.mask,
on: {
click: e => e.target === this.$el && this.close(),
},
},[
h("div", { style: styles.dialog }, [
h("div", { style: styles.header }, this.title),
h("div", { style: styles.content }, this.content),
h("div", { style: styles.footer }, [
h(
"button",
{
style: styles.closeBtn,
on: { click: this.close },
},
"关闭"
),
]),
]),
]
);
},
});
export function showDialog(options) {
const instance = new DialogComponent({
propsData: options,
}).$mount();
document.body.appendChild(instance.$el);
return instance;
}
弹窗工具类
https://halo.jiangling.site/archives/dialog-util