一、为什么要自己动手写插件呢,原因有二:
其一:是因为最近产品了提了一个在web端接收,消息通知的需求,产品要求在若干个页面内如果有消息,就要弹出消息弹窗展示给用户,略加思索之后,第一反应就是写个消息的组件,在需要的页面引入,不过写好之后,发现这样写好麻烦,是不是可以写个插件在全局一次性引入呢?
其二:纯粹的想学习一下vue的插件是如何开发的
二、既然有想法了,那就开始写呗,先去查看了vue的官方文档,官方文档介绍如下:
插件通常用于为 Vue 添加全局级别的功能。然而对于插件,并没有严格限定其使用范围 - 下面是常见的几种插件类型:
-
添加一些全局方法或属性。
-
添加一个或多个全局资源(asset):指令(directives)/过滤器(filters)/过渡(transitions) 等。
-
通过全局 mixin,添加一些组件选项。
-
添加一些 Vue 实例方法,通过把这些方法添加到 Vue.prototype 上实现。
-
一个可以提供 API 的库(library),与此同时也是以上功能的组合。
Vue.js 插件应该暴露一个 install
方法。此方法在调用时,将 Vue
构造函数作为第一个参数传入,以及将一个可选的选项作为第二个参数传入:
1 MyPlugin.install = function (Vue, options) { 2 // 1. 添加全局方法或属性 3 Vue.myGlobalMethod = function () { 4 // 一些逻辑…… 5 } 6 7 // 2. 添加一个全局资源(asset) 8 Vue.directive('my-directive', { 9 bind (el, binding, vnode, oldVnode) { 10 // 一些逻辑…… 11 } 12 ... 13 }) 14 15 // 3. 注入一些组件选项 16 Vue.mixin({ 17 created: function () { 18 // 一些逻辑…… 19 } 20 ... 21 }) 22 23 // 4. 添加一个实例方法 24 Vue.prototype.$myMethod = function (methodOptions) { 25 // 一些逻辑…… 26 } 27 }
1 通过调用全局方法 Vue.use() 使用插件: 2 3 // 调用 `MyPlugin.install(Vue)` 4 Vue.use(MyPlugin) 5 可以根据情况,传入一些可选的选项: 6 7 Vue.use(MyPlugin, { someOption: true }) 8 Vue.use 会自动阻止多次使用同一个插件,所以对于同一个插件的多次调用,将只安装一次。
三、看完文档我们就开始动手写呗(以loading插件为例)
1 var Loading = {} 2 var showLoad = false 3 var loadNode = {} 4 Loading.install = function (Vue, options) { 5 Vue.prototype.$loading = function (type) { 6 if (type === 'close') { 7 loadNode.show = showLoad = false 8 document.querySelector('.loadEffect').remove() 9 } else { 10 if (showLoad) { 11 return 12 } 13 let LoadingTpl = Vue.extend({ 14 data: function () { 15 return { 16 show: showLoad 17 } 18 }, 19 template: `<div class="loadEffect"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><p class="loadings">loading....</p></div> 20 ` 21 }) 22 let tpl = new LoadingTpl().$mount().$el 23 document.body.appendChild(tpl) 24 loadNode.show = showLoad = true; 25 ['open', 'close'].forEach(function (type) { 26 Vue.prototype.$loading[type] = function () { 27 return Vue.prototype.$loading(type) 28 } 29 }) 30 } 31 } 32 } 33 34 export default Loading
import { Loading} from './Plugins/index'
然后在我们的组件中使用this.$loading来使用,发现没有任何问题。。。。。
但是。。。嘿嘿,总有但是,,没错下面的场景就是万恶的但是。。。。
因为我们发现我们编写的这个插件只能在vue组件中使用,如果我想在axios的拦截器中使用这个插件呢?显然用不了,这是为什么呢?是因为我们在axios中没有访问到vue的实例,因为我们的插件是过载在vue的实例上的
现在怎么办,百度看了很多别人写的博客,不出意外,对就是那个不出意外,没有找到合适的解决方案!!!!!!!!!!!!!!!!!
怎么办呢?放弃?不可能,这辈子是不可能放弃的!!!下辈子也不可能的!!!那怎么办?嘿嘿,世面上还是有很多牛叉的UI库的比如element-ui,然后自己去试了一下,发现element-ui不仅在vue组件中可以使用,也可以在axios的拦截器这中调用
既然发现了,那就去查看他们的源码,看看大佬们是如何实现的,不看不知道,一看吓一跳,老大的代码果然性感,下面贴出我自己删减后实现这个功能的核心代码
1 const Message = function (options) { 2 options = options || {} 3 options = { 4 message: options.message, 5 name: options.name, 6 state: options.state 7 } 8 instance = new MessageConstructor({ 9 data: options 10 }) 11 instance.vm = instance.$mount() 12 document.body.appendChild(instance.vm.$el) 13 } 14 Vue.prototype.$message = Message
下面贴出源码地址
https://github.com/songdongdong123/vue-message-Plugins
如果对您有帮助不要吝啬您的start