如果我想,在Vue的prototype上加一个全局属性或者功能,该怎么做呢?
也许你会这样做
import Vue from 'vue'
Vue.prototype.$xxx = function(){
console.log('我是要加的xxx')
}
但是这样其实有一些问题存在的。我们这里是直接对Vue的prototype进行了一个增加属性的操作。那,如果我们是在开发一个轮子,一个组件,发布给其他人使用的话,我们并不知道,这个xxx,在使用你的轮子的人的自己的项目的Vue的prototype上有没有和你的xxx同名的属性存在。如果存在,那就冲突了,侵入性过强了。
这时候你可能会想
我这样做也许可以。
if(Vue.prototype.$xxx === undefined){
Vue.prototype.$xxx = function(){
console.log('我是要加的xxx')
}
}
但这样并不解决问题,如果不是undefined那你的轮子就彻底不能用了吗。
还有一个特别小概率的事件,如果使用你轮子的人,引入的Vue并不是import Vue from 'vue',而是import Vue from 'vue1'或者import Vue from 'vue2'呢?那也不行呀。
所以我们这里需要用到Vue的插件功能。
插件通常用来为 Vue 添加全局功能。
我们这时新建一个例如名叫xxxPlugin.js的文件,写入一个公开的install方法。
export default {
install(Vue,options){
Vue.prototype.$xxx = function(){
console.log('我是要加的xxx')
}
}
}
然后在app.js里全局注册这个插件
接着关键点是:Vue.use(xxxPlugin)
使用你轮子的人,自行决定是不是要根据你提供的useage文档来用Vue.use使用你的轮子。让他自己决定,而不是安装了你的库之后强制用户使用你的这个轮子。
这里也不存在import的问题,因为Vue是这个Vue.use传给你的,并不是你自己的插件import的。
这里举个例子,例如一个toast组件。
index.html
<div id="app">
<button @click="showToast">11</button>
</div>
src/toastPlugin
import Toast from "./Toast";
export default {
install(Vue,options){
Vue.prototype.$toast = function (message){
let Constructor = Vue.extend(Toast)
let toast = new Constructor()
toast.$slots.default = [message]
toast.$mount()
document.body.appendChild(toast.$el)
}
}
}
app.js
import Vue from "vue";
import toastPlugin from "./toastPlugin";
Vue.use(toastPlugin)
new Vue({
el:'#app',
methods:{
showToast(){
this.$toast('我是toast')
}
}
})
这里请注意,在插件里,我们在公开的install方法里在Vue的prototype上加了一个叫$toast的function,在function里我们构造了一个Toast组件实例,并且让这个Toast组件里的<slot></slot>位置的默认值为app.js里的@click事件引发的methodshowToast里传入的传入的'我是toast'。记住这里的message必须是数组[message]。还有,我们必须先让slots的默认值完成赋值,再进行toast.$mount()。不然顺序就反了,mount接着被渲染到body上的toast的slot里不会有内容。所以一定要注意顺序。