如何像Element中的Notification通知组件一样在js代码中就能调用显示呢,项目改造使用了vuetify组件但是它的Notification组件没有提供js api所以只能自己撸一个了。
直接看Element Notification组件的源码,照葫芦画瓢,它可以我就可以。
发现源码中定义了两个文件,一个是js一个是vue的模板,模板文件自然不用多说,关键就在于这个main.js。
import Main from './main.vue'; const NotificationConstructor = Vue.extend(Main); //省略若干行代码 instance = new NotificationConstructor({ data: options }); if (isVNode(options.message)) { instance.$slots.default = [options.message]; options.message = 'REPLACED_BY_VNODE'; } instance.id = id; instance.$mount(); document.body.appendChild(instance.$el); instance.visible = true; instance.dom = instance.$el; instance.dom.style.zIndex = PopupManager.nextZIndex();
阅读源码发现实现步骤如下:
1、导入模板文件然后使用Vue.extend继承得到子类NotificationConstructor;
2、创建一个NotificationConstructor的一个实例(完整的Vue实例,可以调用生命的方法,访问data中的属性等...),instance;
3、instance调用$mount()手动挂载;
4、将$el放到body上就可以显示了。
最后实现基于vuetify的Notification组件,源码如下:
1、vue组件
<template> <v-snackbar v-model="snackbar" top vertical :color="color" :timeout="5000"> <div class="snackbar-content">{{ message }}</div> <v-btn text @click="snackbar = false" class="snackbar-close-btn"> 关闭 </v-btn> </v-snackbar> </template> <script> export default { name: "notification", data() { return { snackbar: false, status: "", message: "", onClose: () => {} }; }, computed: { color() { let color; //下面的bg-success样式需要自己提供,vuetify没有提供对应的样式 switch (this.code) { case "ok": color = "bg-success"; break; case "fail": color = "bg-error"; break; case "error": color = "bg-error"; break; case "warning": color = "bg-warning"; break; case "forbidden": color = "bg-warning"; break; case "missing": color = "bg-warning"; break; case "invalid": color = "bg-error"; break; default: color = "bg-default"; } return color; } }, watch: { snackbar(currVal) { if (!currVal && typeof this.onClose === "function") { this.onClose(); } } }, methods: { setOptions(options) { this.snackbar = true; this.status= options.status; this.message = options.message; this.onClose = options.onClose; } } }; </script> <style scoped> .snackbar-content { word-break: break-all; } .snackbar-close-btn { margin-top: 0 !important; } </style>
2、我这里并没有像element一样使用多实例显示,我只使用了一个实例(多次调用页面上也只会显示一个消息框)
import Vue from "vue"; import Index from "./index.vue"; const NotificationConstructor = Vue.extend(Index); let instance = new NotificationConstructor(); instance.$mount(); document.body.appendChild(instance.$el); instance.visible = true; instance.dom = instance.$el; const Notification = function(options) { options = options || {}; instance.setOptions(options); }; //快捷调用方法 ["ok", "fail", "error", "warning", "forbidden", "missing", "invalid"].forEach( code => { Notification[code] = (options, onClose) => { if (typeof options === "string") { options = { message: options, onClose: onClose }; } options.code = code; return Notification(options); }; } ); export default Notification;
3、在main.js中导入,并使用
import Notification from "@/components/notification"; Vue.prototype.$notify = Notification;
4、在其他vue组件中调用
this.$notify.ok("some message") this.$notify.fail("some message") this.$notify.missing("some message") ...
5、弄完后我想起了vue官网的一句话:“下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。"