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种方式:
- 通过
Vue.use(插件)全局方法进行调用。一般在main.js中调用。 - 插件自动完成了
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 Router2.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 HopkinsonToast制作
下面创建一个提示(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…