3.4.1 this
new Vue({})配置项中的 this 和 Vue.extend({})配置项中的 this 他们分别是谁?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vm 与 vc</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<mc></mc>
</div>
<script>
const myComponent = Vue.extend({
template : `<h1></h1>`,
mounted(){
console.log('vc', this)
}
})
const vm = new Vue({
el : '#app',
components : {
mc : myComponent
},
mounted() {
console.log('vm', this)
},
})
</script>
</body>
</html>
测试结果:
new Vue({})配置项中的 this 就是:Vue 实例(vm)。
Vue.extend({})配置项中的 this 就是:VueComponent 实例(vc)。
打开 vm 和 vc 你会发现,它们拥有大量相同的属性。例如:生命周期钩子、methods、watch 等。
3.4.2 vm === vc ???
只能说差不多一样,不是完全相等。
例如:
vm 上有 el,vc 上没有。
另外 data 也是不一样的。vc 的 data 必须是一个函数。
只能这么说:vm 上有的 vc 上不一定有,vc 上有的 vm 上一定有。
3.4.3 Vue.extend()方法做了什么?
每一次的 extend 调用返回的都是一个全新的 VueComponent 函数。
以下是 Vue.extend()的源码:
注意:是每一次都会返回一个全新的 VueComponent 构造函数。是全新的!!!
构造函数有了,什么时候会调用构造函数来实例化 VueComponent 对象呢?
Vue 在解析
3.4.4 通过 vc 可以访问 Vue 原型对象上的属性
通过 vc 可以访问 Vue 原型对象上的属性:
Vue.prototype.counter = 100
console.log(vc.counter) // 100
为什么要这么设计?代码复用。Vue 原型对象上有很多方法,例如:$mount(),对于组件 VueComponent 来说就不需要再额外提供了,直接使用 vc 调用$mount(),代码得到了复用。
Vue 框架是如何实现以上机制的呢?
VueComponent.prototype.__proto__ = Vue.prototype
测试:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app"></div>
<script>
const userlist = Vue.extend({
template : `<div><h1>用户列表</h1></div>`,
})
const vm = new Vue({
el : '#app',
template : `<userlist></userlist>`,
components : {userlist}
})
console.log(userlist.prototype.__proto__ === Vue.prototype) // true
</script>
</body>
</html>
3.4.4.1 回顾原型对象
prototype 称为:显示的原型属性,用法:函数.prototype,例如:Vue.prototype
proto称为:隐式的原型属性,用户:实例.proto,例如:vm.proto
无论是通过 prototype 还是proto,获取的对象都是同一个,它是一个共享的对象,称为:XX 的原型对象。
如果通过 Vue.prototype 获取的对象就叫做:Vue 的原型对象。
如果通过 User.prototype 获取的对象就叫做:User 的原型对象。
请看下图:
3.4.4.2 原理剖析
VueComponent.prototype.proto = Vue.prototype
这样做的话,最终的结果就是:Vue、vm、VueComponent、vc 都共享了 Vue 的原型对象(并且这个 Vue 的原型对象只有一个)。