继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Vue 进阶系列(二)之插件原理及实现

程序员依扬
关注TA
已关注
手记 58
粉丝 202
获赞 772

高级前端进阶(id:FrontendGaoji)

作者:木易杨,资深前端工程师,前网易工程师,13K star Daily-Interview-Question 作者

https://img3.mukewang.com/5d6a6009000110e905550231.jpg

题图来源于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

第一步先不考虑插件,在已有的VueAPI中是没有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)


打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP