Vue:关于Vue.prototype、Vue.component和Vue.use的使用详解

Vue.prototype

官方原话:
你可能会在很多组件里用到数据/实用工具,但是不想污染全局作用域。这种情况下,你可以通过在原型上定义它们使其在每个 Vue 的实例中可用。

1. 基本示例

main.js中添加一个变量到 Vue.prototype

Vue.prototype.$appName = 'My App'

这样 $appName 就在所有的 Vue 实例中可用了,甚至在实例被创建之前就可以。

new Vue({
  beforeCreate: function () {
    console.log(this.$appName)
  }
})

2、为实例prototype设置作用域

为什么appName要以$开头?这很重要吗?
$是在 Vue 所有实例中都可用的property的一个简单约定。这样做会避免和已被定义的数据、方法、计算属性产生冲突。
如果我们设置:

Vue.prototype.appName = 'My App'

那么如下的代码输出什么:

new Vue({
  data: {
    // 啊哦,`appName` 也是一个我们定义的实例 property 名!
    appName: 'The name of some other app'
  },
  beforeCreate: function () {
    console.log(this.appName)
  },
  created: function () {
    console.log(this.appName)
  }
})

日志中会先出现 “My App”,然后出现 “The name of some other app”
因为this.appName在实例被创建之后被data覆写了。
我们通过$为实例property设置作用域来避免这种事情发生。
你还可以根据你的喜好使用自己的约定,诸如 $_appName 或 ΩappName,来避免和插件或未来的插件相冲突。

3、注册和使用全局变量

每个组件都是一个vue实例Vue.prototype加一个变量,只是给每个组件加了一个属性,这个属性的值并不具有全局性。

  1. 给所有组件注册了一个属性 $appName,赋予初始值'main',所有组件都可以用 this.$appName 访问此变量;
  2. 如果组件中没有赋值,初始值都是'main'.

比如以下例子:
点击 home 中的 change name 再跳转about,about里面还是显示 main in test2

// main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'

Vue.config.productionTip = false
Vue.prototype.$appName = 'main'

new Vue({
    el: '#app',
    store,
    router,
    components: { App },
    template: '<App/>',
})
// home.vue
<template>
  <div>
    <div @click="changeName">change name</div>
    <div @click="gotoTest2">goto test2</div>
  </div>
</template>

<script>
export default {
  methods:{
    changeName(){
      this.$appName = "test1"
    },
    gotoTest2(){
      this.$router.push('/about')
    } 
  }
}
</script>
// about.vue
<template>
  <div>
    <div>{{this.$appName}} in test2</div>
  </div>
</template>

如果要实现全局变量的功能,需要把属性变为引用类型

Vue.prototype.$appName = { name: 'main' }

后面使用this.$appName.name改变和引用相应的值
这进入 about 后显示 test1 in test2

4. 原型方法的上下文

在 JavaScript 中一个原型的方法会获得该实例的上下文,也就是说可以使用 this 访问:数据、计算属性、方法或其它任何定义在实例上的东西。

让我们将其用在一个名为 $reverseText 的方法上:

 // main.js
Vue.prototype.$reverseText = function (propertyName) {
  this[propertyName] = this[propertyName]
    .split('')
    .reverse()
    .join('')
}
// 相应组件
<script>
export default {
  data() {
    return{
      message: 'Hello'
    }
  },
  created() {
    console.log(this.message) // => "Hello"
    this.$reverseText('message')
    console.log(this.message) // => "olleH"
  }
}
</script>

5. 应用示例

5.1 引入 axios

npm install vue-axios --save

npm install qs.js --save  //它的作用是能把json格式的直接转成data所需的格式
// mian.js
import Vue from 'vue'
import axios from 'axios'
import qs from 'qs'

Vue.prototype.$axios = axios    //全局注册,使用方法为:this.$axios
Vue.prototype.qs = qs           //全局注册,使用方法为:this.qs
// 相应组件
<script>
  export default{
    data(){
      return{
        userId:666,         
        token:'',
      }
    },
    created(){
      this.$axios({
        method:'post',
        url:'api',
        data:this.qs.stringify({    //这里是发送给后台的数据
          userId:this.userId,
          token:this.token,
        })
      }).then((response) =>{          //这里使用了ES6的语法
        console.log(response)       //请求成功返回的数据
      }).catch((error) =>{
        console.log(error)       //请求失败返回的数据
      })
    }
  }
</script>

Vue.component(注册或获取全局组件)

官方原话:
Vue.component:注册或获取全局组件

在说注册全局组件之前,我们先说下局部组件,局部组件才是实际开发用的最多的场景。

1、局部组件

1.1 写组件文件

// Children.vue
<template>
  <div>
    <div>组件文件</div>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  },
};
</script>
<style lang="scss" scoped>
</style>

1.2 局部引入组件并使用

<template>
  <div>
    <Children1></Children1>
  </div>
</template>

<script>
import Children from './Children.vue'
export default {
  components: {
    Children
  }
}
</script>

<style scoped></style>

1.3 小结

组件
其实就是日常开发中的写vue文件,每个vue都可以看成是一个组件。
局部组件
A组件引入B组件,并在A组件的components注册并使用。B组件就是一个局部组件。

2、全局组件

全局组件,仅仅是从单文件引入改为在main.js文件中引入即可。

import Vue from 'vue'
import App from './App.vue'

import Children from './views/Children.vue';//引入组件
Vue.component('Children ',Children )//注册组件

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

注意

在日常使用中应该尽量避免使用全局引入,这会大大增加项目体积,
在组件复用性不高的情况下,应该使用局部引入,
只有在组件复用性非常高的时候才应该考虑使用全局引入。

Vue.use(plugin)(使用插件)

官方原话:

安装 Vue.js 插件。
如果插件是一个对象,必须提供 install 方法。
如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。

注意

  1. 通过Vue.use安装 Vue.js 插件,
    • 如果插件是一个对象,那么当Vue.use(插件)之后,插件的install方法会立即执行;
    • 如果插件是一个函数,当Vue.use(插件)之后,函数会被立即执行
  2. Vue.use参数为函数(插件为函数)时,函数的参数是Vue对象.
  3. Vue.use参数为对象(插件为对象)时,它提供的install方法中参数是Vue对象

1、参数为函数

// 新建一个 demo.js ,尝试参数为函数时 Vue.use() 的情况 ,demo.js文件内容如下
function demo (Vue){
    console.log('fn', Vue)
}

export default demo

// 之后在main.js引入demo.js,并且使用 Vue.use() 调用
import demo from '@/components/demo.js'
Vue.use(demo)

查看控制台输出以下结果
在这里插入图片描述

2、参数为对象

// 新建一个 demo.js ,尝试参数为对象时 Vue.use() 的情况 ,demo.js文件内容如下
const demo = {
	// 参数为对象时,需要提供install方法
    install: (Vue) => {
        console.log('obj', Vue)
    }
}

export default demo

// 之后在main.js引入demo.js,并且使用 Vue.use() 调用
import demo from '@/components/demo.js'
Vue.use(demo)

查看控制台输出以下结果
在这里插入图片描述

3、Vue.use() 的源码

import { toArray } from '../util/index'
// Vue.use 源码
export function initUse (Vue: GlobalAPI) {
	// 首先先判断插件plugin是否是对象或者函数:
	Vue.use = function (plugin: Function | Object) {
		const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
		// 判断vue是否已经注册过这个插件,如果已经注册过,跳出方法
		if (installedPlugins.indexOf(plugin) > -1) {
			return this
		}
		
		// 取vue.use参数,toArray() 方法代码在下一个代码块
		const args = toArray(arguments, 1)
		args.unshift(this)
		// 判断插件是否有install方法,如果有就执行install()方法。没有就直接把plugin当Install执行。
		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 方法源码
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
}

三者的区别

1、Vue.prototype

Vue.prototype

  1. 在多个地方都需要使用但不想污染全局作用域的情况下,这样定义,
  2. 在每个 Vue 实例中都可用。
  3. $ 表示这是一个在 Vue 所有实例中都可用的属性,
  4. 常用于方法变量
import echarts from 'echarts'
Vue.prototype.$echarts = echarts 

2、vue.component

全局注册组件

  1. 第一个参数是调用组件时写的组件名,
  2. 第二个参数是引入组件时写的名称,
  3. 可用于注册自定义组件
    • 自定义组件:就是我们自己写的vue文件
  4. 一般情况下,用vue.component注册全局组件的情况不多,多数还是局部组件注册
import myLoading from 'base/loading'
Vue.component('myLoading',myLoading);

3、Vue.use

Vue.use

  1. 如果插件是一个对象,必须提供 install 方法。当Vue.use(插件)之后,插件的install方法会立即执行,install方法中参数是Vue对象
  2. 如果插件是一个函数,它会被作为 install 方法。当Vue.use(插件)之后,函数会被立即执行,函数的参数是Vue对象.
  3. 常用于注册第三方插件。例如:element ui等第三方库
import ElementUI from 'element-ui';
Vue.use(ElementUI);
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值