5.4 建立组件联系

日常开发中,我们可以通过vm.$parent拿到父实例,也可以在父实例中通过vm.$children拿到实例中的子组件。显然,Vue在组件和组件之间建立了一层关联。接下来的内容,我们将探索如何建立组件之间的联系。

不管是父实例还是子实例,在初始化实例阶段有一个initLifecycle的过程。这个过程会把当前实例添加到父实例的$children属性中,并设置自身的$parent属性指向父实例。举一个具体的应用场景:

  1. <div id="app">
  2. <component-a></component-a>
  3. </div>
  4. Vue.component('component-a', {
  5. template: '<div>a</div>'
  6. })
  7. var vm = new Vue({ el: '#app'})
  8. console.log(vm) // 将实例对象输出

由于vue实例向上没有父实例,所以vm.$parentundefinedvm$children属性指向子组件componentA 的实例。

5.4 建立组件联系 - 图1

子组件componentA$parent属性指向它的父级vm实例,它的$children属性指向为空

5.4 建立组件联系 - 图2

源码解析如下:

  1. function initLifecycle (vm) {
  2. var options = vm.$options;
  3. // 子组件注册时,会把父组件的实例挂载到自身选项的parent上
  4. var parent = options.parent;
  5. // 如果是子组件,并且该组件不是抽象组件时,将该组件的实例添加到父组件的$parent属性上,如果父组件是抽象组件,则一直往上层寻找,直到该父级组件不是抽象组件,并将,将该组件的实例添加到父组件的$parent属性
  6. if (parent && !options.abstract) {
  7. while (parent.$options.abstract && parent.$parent) {
  8. parent = parent.$parent;
  9. }
  10. parent.$children.push(vm);
  11. }
  12. // 将自身的$parent属性指向父实例。
  13. vm.$parent = parent;
  14. vm.$root = parent ? parent.$root : vm;
  15. vm.$children = [];
  16. vm.$refs = {};
  17. vm._watcher = null;
  18. vm._inactive = null;
  19. vm._directInactive = false;
  20. // 该实例是否挂载
  21. vm._isMounted = false;
  22. // 该实例是否被销毁
  23. vm._isDestroyed = false;
  24. // 该实例是否正在被销毁
  25. vm._isBeingDestroyed = false;
  26. }

最后简单讲讲抽象组件,在vue中有很多内置的抽象组件,例如<keep-alive></keep-alive>,<slot><slot>等,这些抽象组件并不会出现在子父级的路径上,并且它们也不会参与DOM的渲染。