3.4.1 this

new Vue({})配置项中的 this 和 Vue.extend({})配置项中的 this 他们分别是谁?

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>vm 与 vc</title>
  6. <script src="../js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <mc></mc>
  11. </div>
  12. <script>
  13. const myComponent = Vue.extend({
  14. template : `<h1></h1>`,
  15. mounted(){
  16. console.log('vc', this)
  17. }
  18. })
  19. const vm = new Vue({
  20. el : '#app',
  21. components : {
  22. mc : myComponent
  23. },
  24. mounted() {
  25. console.log('vm', this)
  26. },
  27. })
  28. </script>
  29. </body>
  30. </html>

测试结果:
image.png
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()的源码:
image.png
image.png
注意:是每一次都会返回一个全新的 VueComponent 构造函数。是全新的!!!
构造函数有了,什么时候会调用构造函数来实例化 VueComponent 对象呢?
image.png
Vue 在解析时会创建一个 VueComponent 实例,也就是:new VueComponent()

3.4.4 通过 vc 可以访问 Vue 原型对象上的属性

通过 vc 可以访问 Vue 原型对象上的属性:

  1. Vue.prototype.counter = 100
  2. console.log(vc.counter) // 100

为什么要这么设计?代码复用。Vue 原型对象上有很多方法,例如:$mount(),对于组件 VueComponent 来说就不需要再额外提供了,直接使用 vc 调用$mount(),代码得到了复用。
Vue 框架是如何实现以上机制的呢?

  1. VueComponent.prototype.__proto__ = Vue.prototype

测试:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>测试</title>
  6. <script src="../js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app"></div>
  10. <script>
  11. const userlist = Vue.extend({
  12. template : `<div><h1>用户列表</h1></div>`,
  13. })
  14. const vm = new Vue({
  15. el : '#app',
  16. template : `<userlist></userlist>`,
  17. components : {userlist}
  18. })
  19. console.log(userlist.prototype.__proto__ === Vue.prototype) // true
  20. </script>
  21. </body>
  22. </html>

3.4.4.1 回顾原型对象

prototype 称为:显示的原型属性,用法:函数.prototype,例如:Vue.prototype
proto称为:隐式的原型属性,用户:实例.proto,例如:vm.proto
无论是通过 prototype 还是proto,获取的对象都是同一个,它是一个共享的对象,称为:XX 的原型对象。
如果通过 Vue.prototype 获取的对象就叫做:Vue 的原型对象。
如果通过 User.prototype 获取的对象就叫做:User 的原型对象。
请看下图:
image.png

3.4.4.2 原理剖析

VueComponent.prototype.proto = Vue.prototype
image.png
这样做的话,最终的结果就是:Vue、vm、VueComponent、vc 都共享了 Vue 的原型对象(并且这个 Vue 的原型对象只有一个)。