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

栏目: 编程语言 · 发布时间: 7年前

内容简介:Vue进阶系列汇总如下,欢迎阅读,欢迎加群讨论(文末)。

Vue进阶系列汇总如下,欢迎阅读,欢迎加群讨论(文末)。

Vue 进阶系列(一)之响应式原理及实现

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

使用方法

插件的详细使用方法详情看Vue官网

Vue官网之插件Plugins

概括出来就是

  • 1、通过 Vue.use(MyPlugin) 使用,本质上是调用 MyPlugin.install(Vue)
  • 2、使用插件必须在 new Vue() 启动应用之前完成,实例化之前就要配置好。
  • 3、如果使用 Vue.use 多次注册相同插件,那只会注册成功一次。

源码解读

Vue.use 源码如下

Vue.use = function (plugin) {   
    // 忽略已注册插件
    if (plugin.installed) {
      return
    }
    
    // 集合转数组,并去除第一个参数
    var args = toArray(arguments, 1);
    
    // 把this(即Vue)添加到数组的第一个参数中
    args.unshift(this);
    
    // 调用install方法
    if (typeof plugin.install === 'function') {
      plugin.install.apply(plugin, args);
    } else if (typeof plugin === 'function') {
      plugin.apply(null, args);
    }
    
    // 注册成功
    plugin.installed = true;
    return this;
  };
复制代码

Vue.use 接受一个对象参数 plugin ,首先判断是否已注册,如果多次注册相同插件那么只会注册成功一次,在注册成功后设置 plugin.installed = true 。

然后执行 toArray(arguments, 1) 方法, arguments 是一个表示所有参数的类数组对象,需要转换成数组之后才能使用数组的方法。

function toArray (list, start) {
  start = start || 0;
  var i = list.length - start;
  var ret = new Array(i);
  // 循环去除 前start元素
  while (i--) {
    ret[i] = list[i + start];
  }
  return ret
}
复制代码

上面进行了一次转换,假设 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)。

// ES5
var args = Array.prototype.slice.call(arguments);
var args = [].slice.call(arguments);

// ES6
const args = Array.from(arguments);
const args = [...arguments];
复制代码

转换成数组之后调用 args.unshift(this) ,把 Vue 对象添加到args的第一个参数中,这样就可以在调用 plugin.install 方法的时候把 Vue 对象传递过去。

实例:实现一个插件

要求创建一个告诉Vue组件处理自定义 rules 规则选项的插件,这个 rules 需要一个对象,该对象指定组件中的数据的验证规则。

示例:

const vm = new Vue({
  data: { foo: 10 },
  rules: {
    foo: {
      validate: value => value > 1,
      message: 'foo must be greater than one'
    }
  }
})

vm.foo = 0 // 输出 foo must be greater than one
复制代码

第一步先不考虑插件,在已有的 Vue API中是没有 rules 这个公共方法的,如果要简单实现的话可以通过钩子函数来,即在 created 里面验证逻辑。

const vm = new Vue({
    data: { foo: 10 },
    rules: {
        foo: {
          validate: value => value > 1,
          message: 'foo must be greater than one'
        }
    },
    created: function () {
      
        // 验证逻辑
        const rules = this.$options.rules
        if (rules) {
          Object.keys(rules).forEach(key => {
          
            // 取得所有规则
            const { validate, message } = rules[key]
            
            // 监听,键是变量,值是函数
            this.$watch(key, newValue => {
            
              // 验证规则
              const valid = validate(newValue)
              if (!valid) {
                console.log(message)
              }
            })
          })
        }
      }
    
})

复制代码

可以通过 this.$options.rules 获取到自定义的 rules 对象,然后对所有规则遍历,使用自定义的 validate(newValue) 验证规则。

第二步实现这个 rules 插件,为了在 Vue 中直接使用,可以通过 Vue.mixin 注入到 Vue 组件中,这样所有的 Vue 实例都可以使用。

按照插件的开发流程,应该有一个公开方法 install ,在 install 里面使用全局的 mixin 方法添加一些组件选项, mixin 方法包含一个 created 钩子函数,在钩子函数中验证 this.$options.rules 。

实现代码如下:

import Vue from 'vue'

// 定义插件
const RulesPlugin = {

  // 插件应该有一个公开方法install
  // 第一个参数是Vue 构造器
  // 第二个参数是一个可选的选项对象
  install (Vue) {
  
    // 注入组件
    Vue.mixin({
    
      // 钩子函数
      created: function () {
      
        // 验证逻辑
        const rules = this.$options.rules
        if (rules) {
          Object.keys(rules).forEach(key => {
          
            // 取得所有规则
            const { validate, message } = rules[key]
            
            // 监听,键是变量,值是函数
            this.$watch(key, newValue => {
            
              // 验证规则
              const valid = validate(newValue)
              if (!valid) {
                console.log(message)
              }
            })
          })
        }
      }
    })
  }
}

// 调用插件,实际上就是调用插件的install方法
// 即RulesPlugin.install(Vue)
Vue.use(RulesPlugin)
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

JavaScript Patterns

JavaScript Patterns

Stoyan Stefanov / O'Reilly Media, Inc. / 2010-09-21 / USD 29.99

What's the best approach for developing an application with JavaScript? This book helps you answer that question with numerous JavaScript coding patterns and best practices. If you're an experienced d......一起来看看 《JavaScript Patterns》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试