利用渲染函数,实现动态创建弹窗-Vue3.X
Posted IT飞牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用渲染函数,实现动态创建弹窗-Vue3.X相关的知识,希望对你有一定的参考价值。
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 = () =>
// console.log("remove dom");
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)
/**调用方式: 后两个参数参照渲染函数传参
this.$layer.alert("hello world",title:"title reset",this.$refs.slotRef.innerhtml);
this.$layer.alert("hello world",title:"title reset","<div>内容</div>");
this.$layer.alert("hello world",title:"title reset",h("p","内容"));
this.$layer.alert("hello world",title:"title reset",()=>h(自定义组件,"内容"));
*/
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)
/**
* the same to alert
*/
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>
最终效果
以上是关于利用渲染函数,实现动态创建弹窗-Vue3.X的主要内容,如果未能解决你的问题,请参考以下文章