动态弹窗类组件 = Vue.extend( ) + Vue.extend( ) .$mount( X )
1.Vue.extend( ) 创建子类模板
2.$mount( X ) 用子类模板替换掉 X元素。
Vue2写法
<div :id="domId"></div>
import Vue from "vue";
import Tip from "./Tip.vue";
const TipTemplate = Vue.extend(Tip);
const TipInstance = new this.MonitorTipTemplate().$mount(`#domId`);
//props,不能required校验,会有报错,猜测是$mount的生命周期的原因。
TipInstance.$props.domId = this.domId
Vue3写法(页面单独引入+全局引入)
Tip.vue
<template>
<div class="tip" v-if="isShow">
loading...
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
let isShow = ref(false)
const show = ()=>{
isShow.value = true
}
const hide = ()=>{
isShow.value = false
}
defineExpose({
hide,
show
})
</script>
<style scoped>
.tip{
position: fixed;
display: flex;
inset: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,.8);
font-size: 48px;
justify-content: center;
align-items: center;
}
</style>
Tip.ts
import { App, createVNode, render, VNode } from 'vue'
import Tip from './Tip.vue'
/*
对象:Vue会自动注入到install 方法
function: 就直接在页面使用
*/
// 全局注册
export default {
install(app: App) {
// 创建虚拟dom
const tipVnode: VNode = createVNode(Tip)
// render函数生成真实DOM,
render(tipVnode, document.body)
console.log(tipVnode)
// Vue 全局配置
app.config.globalProperties.$loadingTip = {
show: () => tipVnode.component?.exposed?.show(),
hide: () => tipVnode.component?.exposed?.hide(),
}
},
}
// 页面中引入---函数式返回
export function tip() {
const tipInstance: VNode = createVNode(Tip)
render(tipInstance, document.body)
console.log(tipInstance)
tipInstance.component?.exposed?.show()
}
main.ts
import { createApp } from 'vue'
import Tip from './components/Tip/Tip'
import App from './App.vue'
const app = createApp(App)
app.use(Tip)
app.mount('#app')
app.vue
<template>
<button @click="show">切换</button>
<button @click="fnshow">函数式显示</button>
</template>
<script setup lang="ts">
import { ComponentInternalInstance, getCurrentInstance, reactive ,ref} from "vue";
import {tip} from './components/Tip/Tip'
const {appContext} = getCurrentInstance() as ComponentInternalInstance
const show = ()=>{
console.log(appContext);
appContext.config.globalProperties.$loadingTip.show()
setTimeout(() => {
appContext.config.globalProperties.$loadingTip.hide()
}, 1000);
}
//页面里单独引入
const fnshow = ()=>{
console.log(tip);
tip()
}
</script>
<style>
#app {
width: 1920px;
height: 1080px;
position: relative;
}
</style>
总结:
Vue2 :Vue.extend( ) + $mount( )
Vue3 : createVNode() + render()