Vue2.0版本的动态弹窗创建,请参考:vue利用渲染函数创建弹窗组件,完美支持传值和事件监听(Vue2.X)
基于element-plus框架
文件目录结构
├─ src
│ ├─ ...
│ ├─ package
│ │ ├─ index.ts
│ │ ├─ layer
│ │ │ ├─ alert.vue
│ │ │ ├─ confirm.vue
│ │ │ └─ modal.vue
│ │ └─ layer.ts
代码
src\package\layer.ts
import { createApp, h, render, ref } from "vue";
import alert from "./layer/alert.vue";
import confirm from "./layer/confirm.vue";
import modal from "./layer/modal.vue";
import { ElMessage, MessageParams, ElLoading } from "element-plus";
const layer = function (app: any) {
return {
_create(component: any, props: any, children = {}) {
const defPropsMap: any = {
alert: {
title: "提示",
content: "",
width: 400
},
confirm: {
title: "提示",
content: "",
width: 500
},
modal: {
title: "提示",
content: "",
width: 500
}
};
let Props = { ...defPropsMap[component.name], ...props };
const layerDom = document.createElement('div');
let close = () => {
layerDom.remove();
};
let comRef = ref(null) as any;
let vNode = h({
render() {
return h(component, { ...Props, ref: comRef, "before-close": close }, children)
}
});
let root = Props["_top"] ? (top || self) : self;
root.document.body.appendChild(layerDom);
vNode.appContext = app._context;
render(vNode, layerDom);
return {
el: layerDom,
vm: comRef.value,
close
};
},
alert: function (option: any) {
let opt = {};
let children = {};
if (typeof option === "string") {
opt = Object.assign({}, { content: option, ...arguments[1] })
children = arguments[2] || {};
} else {
opt = option;
children = arguments[1] || {};
}
let layer = this._create(alert, opt || {}, children);
return layer;
},
confirm: function (option: any) {
let opt = {};
let children = {};
if (typeof option === "string") {
opt = Object.assign({}, { content: option, ...arguments[1] })
children = arguments[2] || {};
} else {
opt = option;
children = arguments[1] || {};
}
let layer = this._create(confirm, opt || {}, children);
return layer;
},
modal: function (props = {}, children = {}) {
let layer = this._create(modal, props, children);
return layer;
},
message: function (message: string = "", type: Type = Type.success, option: Object = {}) {
let opt: MessageParams = { message: message, type: "success", ...option };
return ElMessage(opt);
},
loading: function () {
return ElLoading.service({
lock: true,
text: '加载中...',
background: 'rgba(0, 0, 0, 0.7)',
});
}
};
}
export default {
install(app: any, option = {}) {
app.config.globalProperties.$layer = layer(app);
}
};
declare module "@vue/runtime-core" {
interface ComponentCustomProperties {
$layer: {
alert: Function,
confirm: Function,
modal: Function,
loading: Function,
message: Function
},
}
}
enum Type {
success = "success",
warning = "warning",
error = "error",
message = "message"
}
src\package\index.ts
import layer from "./layer";
const install = function (app:any) {
app.config.globalProperties.$layer = layer;
};
export default { install };
src\package\layer\alert.vue
<template>
<el-dialog v-model="isShow" v-bind="$attrs">
<div v-if="content">{{ content }}</div>
<slot></slot>
<template #footer>
<span class="dialog-footer">
<el-button @click="sure">关闭</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import { reactive, toRefs, ref, onMounted } from "vue";
export default {
name: "alert",
emits: ["sure"],
props: ["content"],
setup(props, { expose, attrs, slots, emit }) {
const state = reactive({
isShow: true,
attrs,
});
const actions = {
sure() {
emit("sure", paramCtx);
attrs["before-close"]();
},
};
let paramCtx = { ...attrs, close: attrs["before-close"] };
return {
...toRefs(state),
...actions,
};
},
};
</script>
src\package\layer\confirm.vue
<template>
<el-dialog v-model="isShow" v-bind="$attrs">
<div v-if="content">{{ content }}</div>
<slot></slot>
<template #footer>
<span class="dialog-footer">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="sure">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import { reactive, toRefs, ref } from "vue";
export default {
name: "confirm",
emits: ["sure", "cancel"],
props: ["content"],
setup(props, { expose, attrs, slots, emit }) {
const state = reactive({
isShow: true,
attrs,
});
let paramCtx = { ...attrs, close: attrs["before-close"] };
const actions = {
sure() {
emit("sure", paramCtx);
attrs["before-close"]();
},
cancel() {
emit("cancel", paramCtx);
attrs["before-close"]();
},
};
return {
...toRefs(state),
...actions,
};
},
};
</script>
<style lang="scss" scoped>
</style>
src\package\layer\modal.vue
<template>
<el-dialog v-model="isShow" v-bind="$attrs">
<div v-if="content">{{ content }}</div>
<slot></slot>
</el-dialog>
</template>
<script>
import { reactive, toRefs } from "vue";
export default {
name: "modal",
props: ["content"],
setup(props, { expose, attrs, slots, emit }) {
const state = reactive({
isShow: true,
attrs,
});
return {
...toRefs(state)
};
},
};
</script>
<style lang="scss" scoped>
</style>
src\main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import layer from "./package/layer";
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import { ComponentCustomProperties } from "vue";
createApp(App).use(store).use(router).use(ElementPlus).use(layer).mount('#app')
src\views\Home.vue (如何调用)
<template>
<div class="home">
<el-button @click="alert">alert</el-button>
<el-button @click="confirm">confirm</el-button>
<el-button @click="modal">modal</el-button>
<el-button @click="loading">loading</el-button>
<el-button @click="message">message</el-button>
</div>
</template>
<script lang="ts">
import { defineComponent, h } from "vue";
import com from "@/views/com.vue";
export default defineComponent({
name: "Home",
data() {
return { isShow: true };
},
methods: {
loading() {
let layer = this.$layer.loading();
setTimeout(() => {
layer.close();
}, 2000);
},
message() {
let layer = this.$layer.message("message提示内容");
},
alert() {
let layer = this.$layer.alert("alert提示内容");
},
confirm() {
let layer = this.$layer.confirm("confirm提示内容", {
onSure() {
alert("确定");
layer.close();
},
onCancel() {
alert("取消");
layer.close();
},
});
},
modal() {
let layer = this.$layer.modal(null, () => {
return h(com, {
onSure() {
alert("这里是自定义组件的确定");
layer.close();
},
onCancel() {
alert("这里是自定义组件的取消");
layer.close();
},
});
});
},
},
components: {
com,
},
});
</script>
最终效果
|