【Vue】命令式api组件的封装方法
2023/03/06 14:41:58
Message 组件示例
vue 组件除了常规的注册使用之外还可以通过 api 来调用,例如 ElementUI
中的 this.$message()
方法,一个简单的命令式 api 组件如下:
- message.vue
<template>
<div class="message" v-if="visible">{{ msg }}</div>
</template>
<script>
import Vue from "vue";
const defaultDuration = 1000;
const Message = {
data() {
return {
visible: false,
timer: null,
};
},
props: {
msg: {
type: String,
},
duration: {
type: Number,
default: defaultDuration,
},
},
methods: {
close() {
this.visible = false;
},
show() {
this.visible = true;
clearInterval(this.timer);
this.timer = setTimeout(() => {
this.close();
}, this.duration);
},
},
};
export default Message;
let instanceCache;
export function message(option) {
const msg = option.msg || "";
const duration = option.duration || defaultDuration;
function getInstanceCache() {
if (instanceCache) {
instanceCache.msg = msg;
instanceCache.duration = duration;
} else {
const div = document.createElement("div");
const MessageCtor = Vue.extend(Message);
instanceCache = new MessageCtor({
propsData: {
msg,
duration,
},
});
document.body.append(div);
instanceCache.$mount(div);
}
return instanceCache;
}
const instance = getInstanceCache();
instance.show();
}
</script>
上面的组件有两种使用方式:
注册并使用:
<template> <Message msg="xxx" duration="3000" /> </template> <script> import Message from "../components/Message.vue"; export default { components: { Message, }, }; </script>
通过 api 方式调用:
<script> import { message } from "../components/Message.vue"; message({ msg: "xxx", duration: 2000, }); </script>
命令式 api 组件的封装思路
- 用
Vue.extend()
创建一个用于构造组件实例的组件构造器。 - 用
Vue.extend()
创建的组件构造器创建组件实例,并初始化 props 等数据。 - 调用组件实例的
$mount()
方法将组件挂载到页面的某个元素上。 - 通过暴露 api 的方式将组件实例的操作权限暴露出去,从而达到通过 api 来操控组件的目的。
import Vue from "vue";
import Message from "@/components/Message.vue";
// 初始化组件实例
const compCtor = Vue.extend(Message);
const compInstance = new compCtor();
// 将组件绑定到页面
const div = document.createElement("div");
document.body.appendChild(div);
compInstance.$mount(div);
如何控制组件实例
通过组件实例 compInstance
控制组件:
// 监听组件内部抛出的 $emit('close') 事件
compInstance.$on("close", () => {});
// 修改组件内部变量
compInstance.isShowMessage = true;
为什么组件可以这样用?(Vue 中的组件到底是什么?)
以下内容引自:探索 Vue 高阶组件 | HcySunYang
在 Vue 中组件到底是什么?有的同学可能会有疑问,难道不是函数吗?对,Vue 中组件是函数没有问题,不过那是最终结果,比如我们在单文件组件中的组件定义其实就是一个普通的选项对象,如下:
export default {
methods: {},
mounted() {},
};
当我们从单文件中导入一个组件的时候其实导入的也是一个对象:
import BaseComponent from "./base-component.vue";
console.log(typeof BaseComponent); // object
当这个对象被注册为组件(components
选项)之后,Vue 最终会以该对象创建一个构造函数,该构造函数就是生产组件实例的构造函数。
所以在 Vue 中组件确实是函数,只不过这是最终结果罢了,在这之前我们可以说 Vue 中的组件也可以是一个普通对象,就像单文件组件中所导出的对象一样。
Tips
import 语句可以同时导出默认导出和具名导出:
import Message, { message } from "../components/Message.vue";