Vue插件

编写插件

写 vue 插件稍微复杂一点 😢,根据官网的案例,我们需要提供一个包含 install 方法的对象或者一个函数(传送门),供 Vue.use 调用注册你的插件

写法一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import Component from'./YanProgress.vue'; // 这个就是你平时写的 SFC 组件// 这里要导出一个包含 install 方法的对象let plugin = { // 这里要导出一个 install 方法
install(Vue,options) {
// 这里写你的代码,你可以全局注册组件,也可以写全局指令,也可以扩展 Vue 的方法// 1. 全局组件
Vue.component('yan-progress',Component);
// 2. 全局方法或属性
Vue.myGlobalMethod = function () {
// 逻辑...
}
// 3. 全局指令
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 逻辑...
}
})
// 4. 注入组件
Vue.mixin({
created: function () {
// 逻辑...
}
})
// 5. 添加实例方法
Vue.prototype.$myMethod = function (methodOptions) {
// 逻辑...
}
}
};

if (window && window.Vue) { // 如果是渐进式开发(script 引入简单粗暴的开发方式),需要自动注册你的插件window.Vue.use(plugin);
}

exportdefault plugin;

写法二

1
2
3
4
5
6
7
8
9
10
import Component from'./YanProgress.vue'; // 这个就是你平时写的 SFC 组件// 或者这里也可以写成函数functionplugin(Vue,options) { 
// 这里写你的代码,你可以全局注册组件,也可以写全局指令,也可以扩展 Vue 的方法
Vue.component('yan-progress',Component);
}
};

if (window && window.Vue) { // 如果是渐进式开发(script 引入简单粗暴的开发方式),需要自动注册你的插件window.Vue.use(plugin);
}

exportdefault plugin;

这样写的原因是,下面源码伺候😄

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
export function initUse (Vue: GlobalAPI) {
Vue.use = function (plugin: Function | Object) { // 在这里哦,可以传对象,也可以传函数
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
if (installedPlugins.indexOf(plugin) > -1) { // 避免重复注册插件
return this
}

// additional parameters
const args = toArray(arguments, 1)
args.unshift(this)
if (typeof plugin.install === 'function') { // 如果是带有 install 方法的对象
plugin.install.apply(plugin, args) // 不改变插件的 this(这里的 this 还是指向插件对象本身)
} else if (typeof plugin === 'function') { // 如果是函数
plugin.apply(null, args) // 不改变插件的 this(这里应该是指向window,在浏览器非严格模式下)
}
installedPlugins.push(plugin)
return this
}
}

vue-alert插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import AlertComponent from "./vue-alert.vue"; // 引入先前写好的vue
var Alert = {};
//避免重复install,设立flag
Alert.installed = false;
Alert.install = function(Vue, options) {
if(Alert.installed) return;

Vue.prototype.$alert = (alertMsg, okFun, abortFun) => {
// 如果页面有toast则不继续执行
if(document.querySelector('.vue-alert')) return;
// 1、创建构造器,定义好提示信息的模板
const toastTip = Vue.extend(AlertComponent);
var obj = new toastTip();
//2.数据和函数
if(Object.prototype.toString.call(alertMsg).slice(8, -1).toLowerCase() == 'function') {
obj.okFun = alertMsg;
obj.abortFun = okFun;
obj.alertMsg = '';
} else {
obj.alertMsg = alertMsg;
obj.okFun = okFun;
obj.abortFun = abortFun;
}
//删除弹框
obj.removeAlert = function() {
document.getElementById('zhenwu').removeChild(tpl);
}
//插入页面
let tpl = obj.$mount().$el;
document.getElementById('zhenwu').appendChild(tpl);
Alert.installed = true;
};
};
// 自动安装 ,有了ES6就不要写AMD,CMD了
if(typeof window !== 'undefined' && window.Vue) {
window.Vue.use(Alert)
};

export default Alert
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<template>
<div class="mask vue-alert">
<div class="alert">
<span class="icon"></span>
<p>{{alertMsg||'确定删除该条数据吗?'}}</p>
<div class="btn">
<div class="ok hoverhands" @click="ok">确定</div>
<div class="abort hoverhands" @click="abort">取消</div>
</div>
</div>
</div>
</template>

<script>
export default {
data() {
return {
alertMsg: ''
};
},
created() {

},
methods: {
ok() {
this.okFun&&this.okFun();
this.removeAlert(); //清除弹框
},
abort() {
this.abortFun&&this.abortFun()
this.removeAlert(); //清除弹框
}
},
computed: {

},
components: {

},
directives: {

},
};
</script>

<style scoped="scoped" lang="less">
.mask {
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
position: absolute;
left: 0px;
top: 0px;
display: flex;
justify-content: center;
align-items: center;
z-index: 10000000;
.alert {
width: 362px;
border-top: 3px solid #d1926f;
background: #fff;
.icon {
background: url('../../assets/img/yellow.png');
display: block;
margin: 15px auto;
background-repeat: no-repeat;
background-position: center;
background-size: 32px;
display: block;
margin: 15px auto 5px;
width: 50px;
height: 50px;
}
p {
text-align: center;
font-size: 14px;
}
.btn {
margin-top: 20px;
margin-bottom: 20px;
display: flex;
justify-content: center;
align-items: center;
.ok {
font-size: 12px;
width: 60px;
height: 25px;
line-height: 25px;
color: white;
text-align: center;
background: #fe8242;
}
.abort {
font-size: 12px;
width: 60px;
height: 25px;
line-height: 25px;
color: #525252;
text-align: center;
margin-left: 15px;
background: #f2f2f2;
border: 1px solid #ccc;
}
}
}
}
</style>