const Title = Vue.extend({
template: `<h1>Vue.extend</h1>`
});
const titleComponent = new Title();
console.log(titleComponent); // vue 组件实例
titleComponent.$mount('title'); // 把 上边 template Title 挂载到 html 的 #id title 上去
// 1. 引入对话框组件
import _MessageBox from "./MessageBox.vue";
export default {
// 2. 利用 插件 来完成功能
install(Vue) {
let instance = null;
// 注册 我们创建好的 MessageBox.vue 组件
Vue.component(_MessageBox.name, _MessageBox);
// 在Vue的原型上定义一个全局对象 放置展开 和 关闭 的方法
Vue.prototype.$messageBox = {
show,
hide,
info,
success,
};
// 挂载组件到dom上
function show(props, callback) {
if (!instance) {
// 我们利用 extend 方法拿到组件的 构造器
const MessageBox = Vue.extend({
// 使用 render 函数 将我们 MessageBox.vue 渲染到 instance 里 (虚拟DOM)
render: (h) =>
h("message-box", {
props,
}),
});
// new 构造器 将返回来的实例 放到instance身上, 创建子类的实例 就相当于在视图中基于 <kebab-case> 模式调用了组件
instance = new MessageBox();
// 组件这个组件, 将实例对象 转成 组件 保存到 this.vm 上
this.vm = instance.$mount();
// 当我们渲染了这个组件后就可以拿到 $el. 它就是我们渲染后的真实dom
document.body.appendChild(this.vm.$el);
callback && callback();
}
}
// 销毁挂载到dom上的组件
function hide(callback) {
document.body.removeChild(this.vm.$el);
instance.$destroy();
instance = null;
this.vm = null;
callback && callback();
}
function info(props, callback) {
this.show({ ...props, type: "primary" }, callback);
}
function success(props, callback) {
this.show({ ...props, type: "success" }, callback);
}
},
};
<template>
<div :class="['message-box', type]">
<div class="inner">
<header class="header">
<h1 class="title">{{ title }}</h1>
<span class="close-btn" @click="hideMessageBox">x</span>
</header>
<div class="content">{{ content }}</div>
</div>
</div>
</template>
<script>
export default {
name: 'MessageBox',
props: {
title: {
type: String,
default: "标题默认值"
},
content: {
type: String,
default: "内容默认值"
},
type: {
type: String,
default: "primary",
validator(value) {
return [
'primary',
'success',
'warning',
'danger'
].includes(value);
}
},
},
methods: {
hideMessageBox() {
this.$messageBox.hide(() => {
console.log('关闭');
});
}
}
}
</script>
const app = createApp(App);
const app2 = createApp({
template: `<h1>Vue3 createApp</h1>`,
data() {
return {
title: "Lance",
};
},
});
app2.mount("#title");
app.mount("#app");
MyModal/MyModal.vue
<template>
<teleport to="body" :disabled="false">
<div :class="['modal', type]" v-show="isShow">
<div class="inner">
<header class="hd">
<h1>{{ title }}</h1>
<span @click="isShow = false">x</span>
</header>
<section class="wrap">
<p>{{ content }}</p>
</section>
</div>
</div>
</teleport>
</template>
<script>
export default {
name: "Modal",
props: {
},
data() {
return {
isShow: false,
type: 'primary',
title: 'Default Title',
content: 'Default CONTENT'
};
},
methods: {
openModal() {
this.isShow = true;
},
init({ show, type, title, content }) {
this.isShow = show;
this.setOptions({ type, title, content });
},
open(options) {
this.isShow = true;
this.setOptions(options);
},
setOptions({ type, title, content }) {
this.type = ['primary', 'success', 'warning', 'danger'].includes(type) ? type : this.type;
title && (this.title = title);
content && (this.content = content);
},
primary(options) {
this.isShow = true;
this.setOptions({
...options,
type: 'primary',
});
},
success(options) {
this.isShow = true;
this.setOptions({
...options,
type: 'success',
});
},
...
},
};
</script>
MyModal/index.js
实现 install 方法,挂载组件实例到 app 上
import Modal from "./MyModal.vue";
import { createApp } from "vue";
export default {
install(app) {
const modal = createApp(Modal);
const oFrag = document.createDocumentFragment();
const $modal = modal.mount(oFrag);
app.config.globalProperties.$modal = $modal;
console.log({ modal, $modal }); // 组件实例,应用实例
},
};
index.js