没关系, 面试的时候总会问如何在Vue的实例上挂载一个方法/属性, 也就是Vue.prototype的小技巧, 但是突然有人问他俩有啥关系还真是新鲜.
Vue.prototype
我想应该是网上有文章写Vue.prototype.$xx是用法的, 但是没有说明Vue.use的用法以及Vue.prototype.$xx为什么就能在组件内this.$xx 这么调用, 所以下面我就细细的说下.
Vue.prototype.$xx
this.$xx
看完本文, 能掌握如何定义一个Vue插件, 以及Vue.prototype.$xx的原理.
下面是饿了么UI的引入代码, 大家对这段应该很熟悉了.
import Vue from vue import Element from element-ui Vue.use(Element)
接下来, 我们在看下这个Element是什么
Element
这里我们看到Element是个对象, 上面有version等栏位, 其中还有一个install,他是本文的主角, Vue.use就是要运行这个install对应的函数.
version
install
Vue.use
写一段最少的代码演示如何用Vue.use初始化插件:
// 插件 const plugin = { install(){ document.write(我是install内的代码) } }
// 初始化插件 Vue.use(plugin); // 页面显示"我是install内的代码"
在codepen上看预览
如果想知道插件的具体实现, 请看 https://cn.vuejs.org/v2/guide/plugins.html
Vue.use()
new Vue
好了, 回过头我们再看眼上面的图片, 是不是发现了熟悉的代码:
Vue.prototype.$loading = Loading.service; Vue.prototype.$msgbox = MessageBox; Vue.prototype.$alert = MessageBox.alert; ...
Vue.prototype 的用法我相信大家都会用, 我做过调查, 我就不啰嗦了, 但是我发现大家好像不知道"所以然".
为什么初始化的时候运行了Vue.prototype.$alert, 然后就可以在任意组件内部运行this.$alert()了呢? 首先要了解构造函数, 实例, 原型(prototype)这3个概念.
Vue.prototype.$alert
this.$alert()
这3个概念有点老生常谈了, 百度一搜很多解释, 我先举个例子来和Vue类比你就明白他俩了.
首先我写个假的Vue我们叫他AVue, 恩, 他是个"赝品", "A货", 接下来跟我一步一步走:
Vue
AVue
这里我们只模拟下methods功能.
methods
function AVue({methods}){ for(let key in methods){ this[key] = methods[key]; } }
$alert
AVue.prototype.$alert = ()=>{document.write(我是个赝品!)}
实例化Vue的时候我们知道, 我们会传入一个对象, 对象里面有data/methods等, 我的AVue一样, 下面我们让AVue也学Vue那样实例化:
// 我只山寨了methods, 所以只能学methods喽 const av = new AVue({ methods: { say(){ this.$alert(); } } });
// 调用一下say av.say(); // 我是个赝品!
在codepen上预览
好了, 运行到这里, 我想你应该看明白了吧, 之前大家写的Vue.prototype.$xx其实只不过是js中函数原型的特性罢了: 函数原型上的属性/方法, 在函数实例化后, 可以在任意实例上读取, 要不你也做个"赝品"试下.
vue让大家知道了defineProperty, 我们自己也可以用下他, 比如让Vue.prototype变成不可写的, 防止被覆盖.
Object.defineProperty(Vue.prototype, $alert, { writable: false, value(){ console.log(我是行货!) } });
建议大家可以随便写一个vue的插件练手, 比如我的练手项目就是他:
:lollipop:命令式调用vue组件 https://github.com/any86/vue-create-root