Vue插件你有了解过吗?

2,100 阅读1分钟

Vue的插件式很强大的,插件的功能会使用Vue全局对象或者实例来调用,或者修改从而在Vue的钩子函数内起作用。

Vue.install

Vue的插件必须提供一个公开方法install,这个方法在你使用插件,也就是Vue.use(插件)时被调用,相当于一个插件的注册或者声明。

      // vue => 接受Vue构造器
    // options => 可选的选项对象
插件.install=function(vue,options){
    1.添加全局方法或者属性
    Vue.globalMethod=function(){}
    
    2.添加全局资源
    Vue.directive('my-directive',{
        bind(el,binding,vnode,oldVnode){}
    })
    
    3.添加实例方法,通过把它们添加到Vue.prototype实现
    Vue.prototype.$method=function(options){}

    4.通过mixin方法添加组件选项
    Vue.mixin({
        created:function(){}
    })
}

插件有2种方式:

  1. 通过Vue.use(插件)全局方法进行调用。一般在main.js中调用
  2. 插件自动完成了Vue.use()的调用。这种情况下,插件检测是否存在Vue全局变量,存在就调用Vue.use()。如果项目使用script方式引入的Vue.js,不再再调用Vue.use()。例如:vue-router使用时直接引入,不需要调用Vue.use().

但是模块环境下应当始终显式调用该方法,以保证插件可以正常使用:

   import VueRouter from 'vue-router'
//调用此方法
Vue.use(VueRouter)
//或者传入一个选项对象
Vue.use(VueRouter,{hashbang:true})

常见的插件源码

看看常见插件的实现,看看源码的大概的骨架是怎么样的:

1.vue-router

 let Vue
//class
class Router{
//传入全局配置项
    constructor({
        hashbang=true,
        ......
    }={}){}
}
//避免重复install,设立flag
Router.installed=false
Router.install=function(externalVue){
    if(Route.installed) return
    Vue = externalVue
    ...
    //install完毕
    Router.installed=true
}
// Vue全局变量时,自动install
if(typeof window!=='undefined' && window.Vue){
    window.Vue.use(Router)
}
export defalut Router

2.vue-resource

  //install方法
function plugin(Vue){
    if(plugin.installed){
        return;
    }
}
...
// Vue全局变量时,自动install
if(typeof window!=='undefined' && window.Vue){
    window.Vue.use(plugin);
}
export defalut plugin;

3.vue-touch

var vueTouch={}
vueTouch.config={}
vueTouch.install=function(Vue){
    Vue.directive('touch',{
    ...
})
}
//CommonJs形式
if(typeof exports='object'){
module.exports=vueTouch
}
//AMD形式
else if(typeof define=='function' && define.amd){
define([],function(){return vueTouch})
}
//Vue全局变量时自动调用Vue.use()
else if(window.Vue){
window.VueTouch=vueTouch
Vue.use(Touch)
}   

Vue各种插件开发的过程都是这样,所以掌握大概就可以进行下一步,看一个小demo:

 <body>
    <script type="text/javascript" src=""></script>
    <script type="text/javascript">
    var getName = function(a) {
        console.log('Hello  ' + a)
    }
    var plugin = {}
    
    //**第一种方法:install的方法,方法参数为Vue,在方法内通过赋值创建全局方法
    
    plugin.install = function(Vue) {
        if (plugin.installed) {
            return;
        }
        Vue.myName = getName;

//**第二种方法:用vue的prototype,通过defineProperties创建实例方法
        Object.defineProperties(Vue.prototype, {
            $myName: {
                get() {
                    return {
                        getName: getName
                    }
                }
            }
        });
        
       //注意:mixin混入能力可以把钩子函数(例如created)混入到Vue实例内 
       
        Vue.mixin({
            created: function() {
                console.log('Plugin activiated')
            }
        })
    }
    if (typeof window !== 'undefined' && window.Vue) {
        window.Vue.use(plugin);
    }
    </script>
    <script type="text/javascript">
    var vue = new Vue()
    vue.$myName.getName('Jasonho')//第二种方法
    Vue.myName('Hopkinson')//第一种方法
    </script>
</body>

输出:

   Plugin activiated
Hello  Jasonho
Hello  Hopkinson

Toast制作

下面创建一个提示(Toast)的demo:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <style>
    .vue-tip {
        position: fixed;
        top: 50%;
        left: 50%;
        right: 50%;
        width: 180px;
        height: 40px;
        line-height: 40px;
        padding: 0 10px;
        margin-left: -100px;
        text-align: center;
        z-index: 9999;
        font-size: 14px;
        color: #fff;
        border-radius: 5px;
        background-color: rgba(0, 0, 0, .7);
        animation: showToast .5s;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    
    .vue-tip.tip-bottom {
        bottom: 100px;
        top: inherit;
    }
    
    .vue-tip.tip-top {
        bottom: inherit;
        margin-top: 20px;
        top: 0%;
    }
    
    @keyframes showToast {
        from {
            opacity: 0;
            -webkit-transform: translateY(-10px);
            -moz-transform: translateY(-10px);
            -ms-transform: translateY(-10px);
            -o-transform: translateY(-10px);
            transform: translateY(-10px);
        }
        to {
            opacity: 1;
            -webkit-transform: translateY(0);
            -moz-transform: translateY(0);
            -ms-transform: translateY(0);
            -o-transform: translateY(0);
            transform: translateY(0);
        }
    }
    </style>
</head>

<body>
    <div id="app">
        <button @click="openDefault">默认</button>
        <button @click="openTop">头部</button>
        <button @click="openBottom">尾部</button>
    </div>
    <script type="text/javascript" src=""></script>
    <script type="text/javascript">
    var Tip = {};
    Tip.install = function(Vue, options) {
            let opt = {
                    // 默认显示位置
                    defaultType: "center",
                    // 默认持续时间
                    duration: "3000"
                }
                // 使用options的配置
            for (let i in options) {
                opt[i] = options[i]
            }
            Vue.prototype.$toast = (toast, type) => {
                    // 如果有传type,位置则设为该type
                    var chooseType = type ? type : opt.defaultType;
                    // 如果页面有toast则不继续执行
                    if (document.querySelector('.vue-toast')) return;
                    // 1、创建构造器,定义好提示信息的模板
                    let toastTip = Vue.extend({
                        template: `<div class="vue-tip tip-${chooseType}">${toast}</div>`
                    });
                    // 2、创建实例,挂载到文档以后的地方
                    let tpl = new toastTip().$mount().$el;
                    // 3、把创建的实例添加到body中
                    document.body.appendChild(tpl);
                    // 4.三秒后移除
                    setTimeout(() => {
                        document.body.removeChild(tpl);
                    }, opt.duration)
                }
                // 显示不同的位置
                ['bottom', 'top', 'center'].forEach(type => {
                    Vue.prototype.$toast[type] = (tips) => {
                        return Vue.prototype.$toast(tips, type)
                    }
                })
        }
        // 自动安装
    if (typeof window !== 'undefined' && window.Vue) {
        window.Vue.use(Tip)
    }
    // =====
    // 需要手动安装
    // module.exports = Tip;
    // module.exports = Toast;
    </script>
    <script type="text/javascript">
    var vue = new Vue({
        el: '#app',
        methods: {
            openDefault() {
                this.$toast("默认")
            },
            openTop() {
                this.$toast.top('头部')
            },
            openBottom() {
                this.$toast.bottom('尾部')
            }
        }
    });
    </script>
</body>

</html>   

github:
github.com/hopkinson/v…