高级前端进阶(id:FrontendGaoji)
作者:木易杨,资深前端工程师,前网易工程师,13K star Daily-Interview-Question 作者
题图来源于Daniel Lincoln
使用方法
Vue进阶系列第二弹来啦,如果想要看第一弹请回复[ vue进阶1 ]
插件的详细使用方法详情看Vue官网
概括出来就是
1、通过
Vue.use(MyPlugin)
使用,本质上是调用MyPlugin.install(Vue)
2、使用插件必须在
new Vue()
启动应用之前完成,实例化之前就要配置好。3、如果使用
Vue.use
多次注册相同插件,那只会注册成功一次。
源码解读
Vue.use
源码如下
1Vue.use = function (plugin) {
2 // 忽略已注册插件
3 if (plugin.installed) {
4 return
5 }
6
7 // 集合转数组,并去除第一个参数
8 var args = toArray(arguments, 1);
9
10 // 把this(即Vue)添加到数组的第一个参数中
11 args.unshift(this);
12
13 // 调用install方法
14 if (typeof plugin.install === 'function') {
15 plugin.install.apply(plugin, args);
16 } else if (typeof plugin === 'function') {
17 plugin.apply(null, args);
18 }
19
20 // 注册成功
21 plugin.installed = true;
22 return this;
23 };
Vue.use
接受一个对象参数plugin
,首先判断是否已注册,如果多次注册相同插件那么只会注册成功一次,在注册成功后设置plugin.installed = true
。
然后执行toArray(arguments, 1)
方法,arguments
是一个表示所有参数的类数组对象,需要转换成数组之后才能使用数组的方法。
1function toArray (list, start) {
2 start = start || 0;
3 var i = list.length - start;
4 var ret = new Array(i);
5 // 循环去除 前start元素
6 while (i--) {
7 ret[i] = list[i + start];
8 }
9 return ret
10}
上面进行了一次转换,假设list
是[1, 2, 3, 4],start
是1,首先创建一个包含3个元素的数组,依次执行ret[2] = list[ 2 + 1]
、ret[1] = list[ 1 + 1]
、ret[0] = list[ 0 + 1]
,实际上就是去除arguments
的第一个参数然后把剩余的类数组赋值给新的数组,其实就是去除plugin
参数,因为调用plugin.install
的时候不需要这个参数。
还可以通过如下几种方式实现类数组转换成数组,但是使用slice会阻止某些JavaScript引擎中的优化(参考自MDN)。
1// ES5
2var args = Array.prototype.slice.call(arguments);
3var args = [].slice.call(arguments);
4
5// ES6
6const args = Array.from(arguments);
7const args = [...arguments];
转换成数组之后调用args.unshift(this)
,把Vue
对象添加到args的第一个参数中,这样就可以在调用plugin.install
方法的时候把Vue
对象传递过去。
实例:实现一个插件
要求创建一个告诉Vue组件处理自定义rules
规则选项的插件,这个rules
需要一个对象,该对象指定组件中的数据的验证规则。
示例:
1const vm = new Vue({
2 data: { foo: 10 },
3 rules: {
4 foo: {
5 validate: value => value > 1,
6 message: 'foo must be greater than one'
7 }
8 }
9})
10
11vm.foo = 0 // 输出 foo must be greater than one
第一步先不考虑插件,在已有的Vue
API中是没有rules
这个公共方法的,如果要简单实现的话可以通过钩子函数来,即在created
里面验证逻辑。
1const vm = new Vue({
2 data: { foo: 10 },
3 rules: {
4 foo: {
5 validate: value => value > 1,
6 message: 'foo must be greater than one'
7 }
8 },
9 created () {
10
11 // 验证逻辑
12 const rules = this.$options.rules
13 if (rules) {
14 Object.keys(rules).forEach(key => {
15
16 // 取得所有规则
17 const { validate, message } = rules[key]
18
19 // 监听,键是变量,值是函数
20 this.$watch(key, newValue => {
21
22 // 验证规则
23 const valid = validate(newValue)
24 if (!valid) {
25 console.log(message)
26 }
27 })
28 })
29 }
30 }
31
32})
可以通过this.$options.rules
获取到自定义的rules
对象,然后对所有规则遍历,使用自定义的validate(newValue)
验证规则。
第二步实现这个rules
插件,为了在Vue
中直接使用,可以通过Vue.mixin
注入到Vue
组件中,这样所有的Vue
实例都可以使用。
按照插件的开发流程,应该有一个公开方法install
,在install
里面使用全局的mixin
方法添加一些组件选项,mixin
方法包含一个created
钩子函数,在钩子函数中验证this.$options.rules
。
实现代码如下:
1import Vue from 'vue'
2
3// 定义插件
4const RulesPlugin = {
5
6 // 插件应该有一个公开方法install
7 // 第一个参数是Vue 构造器
8 // 第二个参数是一个可选的选项对象
9 install (Vue) {
10
11 // 注入组件
12 Vue.mixin({
13
14 // 钩子函数
15 created () {
16
17 // 验证逻辑
18 const rules = this.$options.rules
19 if (rules) {
20 Object.keys(rules).forEach(key => {
21
22 // 取得所有规则
23 const { validate, message } = rules[key]
24
25 // 监听,键是变量,值是函数
26 this.$watch(key, newValue => {
27
28 // 验证规则
29 const valid = validate(newValue)
30 if (!valid) {
31 console.log(message)
32 }
33 })
34 })
35 }
36 }
37 })
38 }
39}
40
41// 调用插件,实际上就是调用插件的install方法
42// 即RulesPlugin.install(Vue)
43Vue.use(RulesPlugin)