vue3中用全局服务的形式调用一个组件
在vue项目中,通常使用一个组件需要在template
中以标准的标签形式来显示的使用,但是很多时候,我不希望写模板语法,而是希望通过纯js函数调用的形式来调用组件,那么又应该如何做呢?今天就参考element-plus
来编写一个message
组件,主要是记录一下这个过程。
使用过element ui
的人都知道它提供了很多全局方法来调用组件,比如一个提示组件message
,其主要有两种用法:
- 全局注册了组件后,在组件内部全局属性直接使用
// main.js
import message from './message.js'
app.use(message)
// 组件内部
this.$message.success('xxxx')
this.$message({
type:'success',
message:'成功2'
})
- 通过导入服务的形式调用 ,可以用于选项式或者setup中通用
import message from './message.js'
message({
type:'success',
message:'成功'
})
message.success('成功')
message.success('失败')
- 好废话不多说,我们先得有这么一个sfc组件,基本代码如下: message.vue
<template>
<div class="message" :class="type ? 'message-' + type : ''">
<span>{{ message }}</span>
<span class="close" @click="close">x</span>
</div>
</template>
<script setup>
import { defineProps, defineOptions, useAttrs } from "vue";
defineOptions({
inheritAttrs: false,
});
const attrs = useAttrs();
const props = defineProps({
message: {
type: String,
},
type: {
type: String,
},
duration: {
type: Number,
default: 3000,
},
});
function close() {
if(props.duration){
attrs.close && attrs.close();
}
}
</script>
<style scoped>
.message {
padding: 8px 16px;
border-radius: 4px;
background-color: #ddd;
display: flex;
justify-content: space-between;
color: #fff;
}
.close {
cursor: pointer;
}
.message-success {
background-color: #67c23a;
}
.message-error {
background-color: #f56c6c;
}
</style>
要想通过app的use方法并且注册组组件,首先需要暴露一个函数,或者一个提供了install
方法的对象,如下:
message.js
import { createVNode, render } from "vue";
import Message from "./message.vue";
function getInstance(config) {
const div = document.createElement("div");
const conf = Object.assign({}, config);
if (conf.duration === undefined) {
conf.duration = 3000;
}
const close = () => {
try {
document.body.removeChild(div);
} catch (error) {}
};
conf.close = close;
const vnode = createVNode(Message, conf);
render(vnode, div);
document.body.appendChild(div);
if (conf.duration) {
setTimeout(() => {
try {
document.body.removeChild(div);
} catch (error) {
}
}, conf.duration);
}
return {
close,
};
}
const message = (opts) => {
return getInstance(opts);
};
message.install = (app) => {
// 这样就可以值选项式api中通过this.$message的形式调用了 返回一个包含close的对象,可以手动关闭,也支持自动关闭
app.config.globalProperties.$message = message;
};
export default message;
为了丰富常用功能,需要给message提供两个快捷方法:
message.success = (msg) => {
let conf = {
type: "success",
message: msg,
};
return getInstance(conf);
};
message.error = (msg) => {
let conf = {
type: "success",
message: msg,
};
return getInstance(conf);
};
至此第一种方式通过this调用可以了,聪明的你也一定发现,其实可以不用全局注册,然后组合式api中直接导入message,然后就可以服务的形式来调用了。
最后,看了vue3的实现方式,是不是非常简单呢?你学废了吗?当然请想一下如果vue2又该如何实现呢? 欢迎点赞收藏吐槽指点。
转载自:https://juejin.cn/post/7244802984118190140