基于单例模式下实现的vue全局组件
前言
前段时间,公司产品提了一个需求,希望可以有一个图片查看器,不是蒙层形式,支持边看图片边操作其它,并支持拖动。当然,具体的业务需求比这复杂的多,基于以上功能放弃了使用elment-ui的<el-image>
,而是从无到有实现一个图片查看器。然而,本文不是讲如何实现图片查看器,而是如何实现一个全局的组件,像消息组件那样方便调用。
实现一个简单的图片查看组件
<template>
<span class="box" v-if="visible">
<img :src="url" alt="加载失败" />
</span>
</template>
<script>
export default {
name: "viewer",
data() {
return {
visible: false,
url: "",
};
},
};
</script>
<style scoped>
.box {
padding: 10px;
background: pink;
border-radius: 4px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
基于Vue.extend()构造出vue子类
Vue.extend(options)用法:使用基础Vue构造器,创建一个“子类”。参数是一个包含组件选项的对象。
注意:
data
选项是特例,在Vue.extend()
中它必须是函数
import Vue from "vue";
import Message from "./Message.vue";
const Component = Vue.extend(Message);
let instance = null;
function MessageBox(options) {
// 单例模式,先判断实例是否存在,保证页面上只存在一个实例组件
if (!instance) {
instance = new Component({
el: document.createElement("div"),
data() {
return options;
}
});
document.body.appendChild(instance.$el);
// 上一步刚挂载dom,因此使用nextick确保dom已更新
Vue.nextTick(() => {
instance.visible = true;
});
} else {
// 存在实例,则合并options,更新视图
instance.visible = true;
Object.assign(instance, options);
}
}
// 提供close方法,方便直接调用
MessageBox.close = () => {
if (instance) {
instance.visible = false;
}
};
export default {
// 提供install方法,便于Vue.use()注册。将方法挂载在Vue原型上,方便全局使用。
install() {
Vue.prototype.$message = MessageBox;
}
};
Vue.use()注册
在main.js
中:
import Vue from "vue";
import App from "./App.vue";
import MessageBox from "./components/index.js";
// 注册组件
Vue.use(MessageBox);
Vue.config.productionTip = false;
new Vue({
render: (h) => h(App)
}).$mount("#app");
让我们来写个页面调用看看,是否可行
这里借助了一个生成随机图片的接口
https://picsum.photos/200/200?random=1
,来测试图片的切换效果。
<template>
<div id="app">
<button @click="click(1)">图片1</button>
<button @click="click(2)">图片2</button>
<button @click="click(3)">图片3</button>
<button @click="click(4)">图片4</button>
<button @click="close">关闭</button>
</div>
</template>
<script>
export default {
name: "App",
methods: {
click(key) {
this.$message({
text: `图片${key}`,
url: `https://picsum.photos/200/200?random=${key}`,
});
},
close() {
this.$message.close();
},
},
};
</script>
效果图
来回切换图片,无问题,关闭也无问题。
文本代码皆在
codesandbox
中实现的,想看效果的:codesandbox.io/s/brave-vil…
总结
- 基于Vue.extend()实现一个全局组件
- 实现单例模式下的全局组件
尽管该案例无法实现业务的需求,实际开发中也没有使用此方法,因为无法实现vuex数据通信的能力,但作为一个实际开发中遇到的场景,简单的demo功能也够用了。
转载自:https://juejin.cn/post/7072704321774682119