Vue经典面试题: Vue.use和Vue.prototype.$xx有血缘关系吗?

有关系吗?

不要紧, 面试的时候总会问如何在Vue的实例上挂载一个方法/属性, 也就是Vue.prototype的小技巧, 可是忽然有人问他俩有啥关系还真是新鲜. javascript

我想应该是网上有文章写 Vue.prototype.$xx是用法的, 可是没有说明Vue.use的用法以及 Vue.prototype.$xx为何就能在组件内 this.$xx 这么调用, 因此下面我就细细的说下.

说能学会啥?

看完本文, 能掌握如何定义一个Vue插件, 以及Vue.prototype.$xx的原理.html

Vue.use

用饿了么UI举例

下面是饿了么UI的引入代码, 你们对这段应该很熟悉了.前端

import Vue from 'vue'
import Element from 'element-ui'
Vue.use(Element)
复制代码

接下来, 咱们在看下这个Element是什么vue

这里咱们看到 Element是个对象, 上面有 version等字段, 其中还有一个 install,他是本文的主角, Vue.use就是要运行这个 install对应的函数.

最小结构

写一段最少的代码演示如何用Vue.use初始化插件:java

// 插件
const plugin = {
  install(){
    document.write('我是install内的代码')
  }
}

// 初始化插件
Vue.use(plugin); // 页面显示"我是install内的代码"
复制代码

在codepen上看预览 若是想知道插件的具体实现, 请看 cn.vuejs.org/v2/guide/pl…git

总结

  1. Vue的插件是一个对象, 就像Element.
  2. 插件对象必须有install字段.
  3. install字段是一个函数.
  4. 初始化插件对象须要经过Vue.use().

扩展学习

  1. Vue.use()调用必须在new Vue以前.
  2. 同一个插件屡次使用Vue.use()也只会被运行一次.

Vue.prototype.$xx

好了, 回过头咱们再看眼上面的图片, 是否是发现了熟悉的代码:github

Vue.prototype.$loading = Loading.service;
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;
...
复制代码

Vue.prototype 的用法我相信你们都会用, 我作过调查, 我就不啰嗦了, 可是我发现你们好像不知道"因此然".面试

因此然

为何初始化的时候运行了Vue.prototype.$alert, 而后就能够在任意组件内部运行this.$alert()了呢? 首先要了解构造函数, 实例, 原型(prototype)这3个概念.element-ui

构造函数, 实例, 原型(prototype)

这3个概念有点老生常谈了, 百度一搜不少解释, 我先举个例子来和Vue类比你就明白他俩了.微信

首先我写个假的Vue咱们叫他AVue, 恩, 他是个"赝品", "A货", 接下来跟我一步一步走:

1. AVue是个构造函数

这里咱们只模拟下methods功能.

function AVue({methods}){
	for(let key in methods){
		this[key] = methods[key];
	}
}
复制代码

2. 给AVue的原型上放个$alert

AVue.prototype.$alert = ()=>{document.write('我是个赝品!')}
复制代码

3. 实例化AVue

实例化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组件 github.com/any86/vue-c…

微信群

感谢你们的阅读, 若有疑问能够加群🚀, 群里有好多有趣的前端的小伙伴, 让咱们共同窗习成长吧!

也可加我微信, 我拉你进入微信群(因为腾讯对微信群的100人限制, 超过100人后必须由我拉进去)

相关文章
相关标签/搜索