欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈vue.use()方法从源码到使用

程序员文章站 2023-12-03 09:22:52
关于 vue.use 我们都知道些什么? 在做 vue 开发的时候大家一定经常接触 vue.use() 方法,官网给出的解释是: 通过全局方法 vue.use() 使...

关于 vue.use 我们都知道些什么?

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

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 实例,我们来写一个简单的例子证明一下。

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 方法内部实现了什么逻辑就由插件自身的业务决定了。

源码分析

首先说一下 flow,vue源码中那些奇怪的写法 vue.use = function (plugin: function | object) 是 flow 的语法,flow 是 facebook 出品的 javascript 静态类型检查工具。javascript 是动态类型语言,它的灵活性有目共睹,但是过于灵活的副作用是很容易就写出非常隐蔽的隐患代码,在编译期甚至看上去都不会报错,但在运行阶段就可能出现各种奇怪的 bug。

下面我们正式开始分析源码,vue.use() 的源码很简单30行都不到,首先看 src/core/global-api/use.js 下 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
  }
  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
 }
}

上面源码中使用了工具函数 toarray ,该函数定义在 src/shared/util.js

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
}

了解一下源码实现了什么逻辑

vue.use = function (plugin: function | object) {

在全局api vue 上定义了 use 方法,接收一个 plugin 参数可以是 function 也可以是 object,这就和前面官方规定的 vue.use() 第一个参数要求的类型对应上了。

if (installedplugins.indexof(plugin) > -1) {

用来判断该插件是不是已经注册过,防止重复注册。

const args = toarray(arguments, 1)

arguments是 vue.use() 方法的参数列表是一个类数组,后面的 1 先理解成一个常量,toarray 方法的作用就是把第一个 array 参数从下标为1截取到最后。也就拿到了 vue.use() 方法除去第一个之外的其他参数,这些参数准备在调用 instll 方法的时候传入。

if (typeof plugin.install === 'function') {
} else if (typeof plugin === 'function') {

这里的if语句是判断 vue.use() 传入的第一个参数是 object 还是 function。

plugin.install.apply(plugin, args)
plugin.apply(null, args)

判断完之后执行那个对应的 install 方法,用 apply 改变 this 指向,并把 toarray 得到的剩余参数传入。

installedplugins.push(plugin)

最后记录该组件已经注册过了

现在我们发现 vue.use() 的注册本质上就是执行了一个 install 方法,install 里的内容由开发者自己定义,通俗讲就是一个钩子可能更贴近语义化而已。

vue.use()有什么用

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

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

echarts 用 vue.use() 来注册

main.js

import vue from 'vue'
import echarts from './echarts.js'
vue.use(echarts)

new vue({
 ...
})

echarts.js

import echarts from 'echarts'
export default {
 install(vue){
  vue.prototype.$echarts = echarts
 }
}

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

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

base.js

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

import vue from 'vue'
import base from './base.js'
vue.use(base)

new vue({
 ...
})

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。