在做 vue 开发的时候大家一定经常接触 Vue.use() 方法,官网给出的解释是: 通过全局方法 Vue.use() 使用插件;我觉得把使用理解成注册更合适一些,首先看下面常见的注册场景。

1
2
3
4
5
6
7
8
import Router from 'vue-router'
Vue.use(Router)
 
import Vuex from 'vuex'
Vue.use(Vuex)
 
import Echarts from 'echarts'
Vue.prototype.$echarts = Echarts

关于 echarts 的注册很简单,直接挂在 Vue 方法的原型上,通过原型链继承的关系可以在任意一个组件里通过 this.$echarts 访问到 echarts 实例,我们来写一个简单的例子证明一下。

1
2
3
4
5
6
7
8
function myVue(title){
 this.title = title
}
myVue.prototype.myUse = '在原型上添加公共属性'
const A = new myVue('我是实例A')
const B = new myVue('我是实例B')
console.log(A.title, B.title, A.myVue, B.myVue, )
// 我是实例A 我是实例B 在原型上添加公共属性 在原型上添加公共属性

而 Router 和 Vuex 的注册就要去分析 Vue.use() 的源码了,在分析源码之前先总结一下官方对 Vue.use() 方法的说明:

  • 通过全局方法 Vue.use() 使用插件
  • Vue.use 会自动阻止多次注册相同插件
  • 它需要在你调用 new Vue() 启动应用之前完成
  • Vue.use() 方法至少传入一个参数,该参数类型必须是 Object 或 Function,如果是 Object 那么这个 Object 需要定义一个 install 方法,如果是 Function 那么这个函数就被当做 install 方法。在 Vue.use() 执行时 install 会默认执行,当 install 执行时第一个参数就是 Vue,其他参数是 Vue.use() 执行时传入的其他参数。

官网说 Vue.use() 是用来使用插件的,那么传入的 Router 和 Vuex 就是这里指的插件,而这个插件本质上又是一个 install 方法。至于 install 方法内部实现了什么逻辑就由插件自身的业务决定了。

vue.use()源码


下面切入本文的主题。我们知道了vue.use()怎么用还不够,还要知道它的内部是怎么实现的。下面展示源码:

import { toArray } from '../util/index'

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') {
plugin.install.apply(plugin, args)
} else if (typeof plugin === 'function') {
plugin.apply(null, args)
}
installedPlugins.push(plugin)
return this
}
}

vue.use()源码中采用了flow的语法。flow语法,官方解释是:

Flow is a static type checker for your JavaScript code. It does a lot of work to make you more productive. Making you code faster, smarter, more confidently, and to a bigger scale.

简单的意思就是flow是JavaScript代码的静态类型检查工具。官网链接
使用flow的好处就是:在编译期对js代码变量做类型检查,缩短调试时间, 减少因类型错误引起的bug。我们都知道js是解释执行语言,运行的时候才检查变量的类型,flow可以在编译阶段就对js进行类型检查。

下面将对vue.use()源码进行解读:

1、首先先判断插件plugin是否是对象或者函数:
Vue.use = function (plugin: Function | Object)

2、判断vue是否已经注册过这个插件
installedPlugins.indexOf(plugin) > -1
如果已经注册过,跳出方法

3、取vue.use参数。
const args = toArray(arguments, 1)

4、toArray()取参数
代码:

export function toArray (list: any, start?: number): Array<any> {
start = start || 0
let i = list.length - start
const ret: Array<any> = new Array(i)
while (i--) {
ret[i] = list[i + start]
}
return ret
}

let i = list.length - start意思是vue.use()方法传入的参数,除第一个参数外(第一个参数是插件plugin),其他参数都存储到一个数组中,并且将vue对象插入到参数数组的第一位。最后参数数组就是[vue,arg1,arg2,...]

5、判断插件是否有install方法,如果有就执行install()方法。没有就直接把plugin当Install执行。

if (typeof plugin.install === 'function') {
plugin.install.apply(plugin, args)
} else if (typeof plugin === 'function') {
plugin.apply(null, args)
}

plugin.install.apply(plugin, args)将install方法绑定在plugin环境中执行,并且传入args参数数组进install方法。此时install方法内的this指向plugin对象。
plugin.apply(null, args) plugin内的this指向null.

最后告知vue该插件已经注册过installedPlugins.push(plugin)保证每个插件只会注册一次。

Vue.use()有什么用

在 install 里我们可以拿到 Vue 那么和 Vue 相关的周边工作都可以考虑放在 Vue.use() 方法里,比如:

  • directive注册
  • mixin注册
  • filters注册
  • components注册
  • prototype挂载
  • ...

echarts 用 Vue.use() 来注册

main.js

1
2
3
4
5
6
7
import Vue from 'vue'
import echarts from './echarts.js'
Vue.use(echarts)
 
new Vue({
 ...
})

echarts.js

1
2
3
4
5
6
import Echarts from 'echarts'
export default {
 install(Vue){
  Vue.prototype.$echarts = Echarts
 }
}

这样写的好处是可以在 install 的文件里做更多配置相关的工作,main.js 不会变的臃肿,更方便管理。

全局组件用 Vue.use() 来注册

base.js

1
2
3
4
5
6
7
8
import a from './a'
import b from './b'
let components = { a, b }
const installBase = {
 install (Vue) {
  Object.keys(components).map(key => Vue.component(key, components[key]))
 }
}

main.js

1
2
3
4
5
6
7
import Vue from 'vue'
import base from './base.js'
Vue.use(base)
 
new Vue({
 ...
})

vue.use()方法从源码到使用的更多相关文章

  1. Vue.js 2.0源码解析之前端渲染篇

    一.前言 Vue.js框架是目前比较火的MVVM框架之一,简单易上手的学习曲线,友好的官方文档,配套的构建工具,让Vue.js在2016大放异彩,大有赶超React之势.前不久Vue.js 2.0正式 ...

  2. 如何实现全屏遮罩(附Vue.extend和el-message源码学习)

    [Vue]如何实现全屏遮罩(附Vue.extend和el-message源码学习) 在做个人项目的时候需要做一个类似于电子相册浏览的控件,实现过程中首先要实现全局遮罩,结合自己的思路并阅读了(饿了么) ...

  3. Scala 深入浅出实战经典 第41讲:List继承体系实现内幕和方法操作源码揭秘

    Scala 深入浅出实战经典 第41讲:List继承体系实现内幕和方法操作源码揭秘 package com.parllay.scala.dataset /** * Created by richard ...

  4. [Java源码解析] -- String类的compareTo(String otherString)方法的源码解析

    String类下的compareTo(String otherString)方法的源码解析 一. 前言 近日研究了一下String类的一些方法, 通过查看源码, 对一些常用的方法也有了更透彻的认识,  ...

  5. Pycharm中查看方法的源码

    方法1.鼠标放在函数上,Ctrl+B,看源码 方法2.将光标移动至要查看的方法处,按住ctrl 键,点击鼠标左键,即可查看该方法的源码.

  6. 如何查看laravel门脸类包含方法的源码

    以Route门脸类为例,我们定义路由时使用的就是Route门脸类,例如我们在web.php中定义的路由 use Illuminate\Support\Facades\Route; Route::get ...

  7. 《JAVA高并发编程详解》-Thread start方法的源码

    Thread start方法的源码:

  8. HttpServlet中service方法的源码解读

    前言     最近在看<Head First Servlet & JSP>这本书, 对servlet有了更加深入的理解.今天就来写一篇博客,谈一谈Servlet中一个重要的方法-- ...

  9. vue UI库iview源码解析(2)

    上篇问题 在上篇<iview源码解析(1)>中的index.js 入口文件的源码中有一段代码有点疑惑: /** * 在浏览器环境下默认加载组件 */ // auto install if ...

随机推荐

  1. 计算某天的下一天:黑盒测试之等价类划分+JUnit参数化测试

    题目要求 测试以下程序:该程序有三个输入变量month.day.year(month.day和year均为整数值,并且满足:1≤month≤12.1≤day≤31和1900≤year≤2050),分别 ...

  2. C#多线程(13):任务基础①

    目录 多线程编程 多线程编程模式 探究优点 任务操作 两者创建任务的方式 Task.Run() 创建任务 取消任务和控制任务的创建 任务返回结果以及异步获取返回结果 捕获任务异常 全局捕获任务异常 多 ...

  3. Spring Cloud 系列之 Sleuth 链路追踪(三)

    本篇文章为系列文章,未读前几集的同学请猛戳这里: Spring Cloud 系列之 Sleuth 链路追踪(一) Spring Cloud 系列之 Sleuth 链路追踪(二) 本篇文章讲解 Sleu ...

  4. python学习22之函数式编程

    '''''''''1.高阶函数:将函数作为参数传递到另一个函数中,作为这个函数的参数,这样的方式叫高阶函数(1)map:两个参数,一个是函数,一个是iterator,将函数依次作用于Iterator中 ...

  5. Python与Excel交互——Xlwings实战

    这一期直接来实战. 比如说,我们在一个快递网站上爬取了几个快递的轨迹信息,我们需要将数据保存下来,一个常规做法是把数据保存在数据库里(Mysql,MongoDB,Redis),另一个是用Excel的形 ...

  6. poj_1323 Game Prediction 贪心

    Game Prediction Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11814   Accepted: 5701 ...

  7. Linux硬盘分区知识

    前言 硬盘使用前,一般要分区,格式化(创建文件系统)<== 存放数据 类比,房子使用前,一般要隔断,装修,买家具,再住人. 分区 一块硬盘: 主分区.扩展分区.逻辑分区 主分区+扩展分区的数量& ...

  8. FluxInterval实例及解析

    为什么80%的码农都做不了架构师?>>>   序 本文主要研究下FluxInterval的机制 FluxInterval reactor-core-3.1.3.RELEASE-sou ...

  9. 原生JS设计轮播图

    一.效果预览: 由于只能上传2M以下的图片,这里只截取了自动切换的效果: 二.编写语言 HTML.CSS.原生JS 三.编写思路 (一)HTML部分 1..slide意为滑槽,里面存放所有图片: 2. ...

  10. 关于【MySQL 子查询——查询最大值】的补充说明

    昨天在使用子查询查找最高分和最低分时遇上了一点问题,情况是这样的:如果找到的最高分或最低分是唯一值则不会有什么问题,但如果有其它班级学生的成绩恰好与查询的最高分或最低分相同时就会把那个学生的信息也显示 ...