13.4 抽象组件

这一节的最后顺便提一下上文提到的抽象组件的概念。Vue提供的内置组件都有一个描述组件类型的选项,这个选项就是{ astract: true },它表明了该组件是抽象组件。什么是抽象组件,为什么要有这一类型的区别呢?我觉得归根究底有两个方面的原因。

    • 抽象组件没有真实的节点,它在组件渲染阶段不会去解析渲染成真实的dom节点,而只是作为中间的数据过渡层处理,在keep-alive中是对组件缓存的处理。
    • 在我们介绍组件初始化的时候曾经说到父子组件会显式的建立一层关系,这层关系奠定了父子组件之间通信的基础。我们可以再次回顾一下initLifecycle的代码。
  1. Vue.prototype._init = function() {
  2. ···
  3. var vm = this;
  4. initLifecycle(vm)
  5. }
  6. function initLifecycle (vm) {
  7. var options = vm.$options;
  8. var parent = options.parent;
  9. if (parent && !options.abstract) {
  10. // 如果有abstract属性,一直往上层寻找,直到不是抽象组件
  11. while (parent.$options.abstract && parent.$parent) {
  12. parent = parent.$parent;
  13. }
  14. parent.$children.push(vm);
  15. }
  16. ···
  17. }

子组件在注册阶段会把父实例挂载到自身选项的parent属性上,在initLifecycle过程中,会反向拿到parent上的父组件vnode,并为其$children属性添加该子组件vnode,如果在反向找父组件的过程中,父组件拥有abstract属性,即可判定该组件为抽象组件,此时利用parent的链条往上寻找,直到组件不是抽象组件为止。initLifecycle的处理,让每个组件都能找到上层的父组件以及下层的子组件,使得组件之间形成一个紧密的关系树。

有了第一次的缓存处理,当第二次渲染组件时,keep-alive又会有哪些魔法的存在呢,之前留下的缓存优化又是什么?这些都会在下一小节一一解开。