VUE源码分析之$parent $children 原理

我们在父组件中通过$children获取到子组件中的数据,同样我们在子组件中通过$parent可以获取到父组件中的数据。看下这个简单例子:

<script src="./vue.js"></script>
<div id="app">
    <child-comp></child-comp>
</div>
<script>
 
    Vue.component('child-comp', {
        template: "<div></div>",

        data: function(){

              return {

                    msg: "here is child data"

              }

        }
        mounted: function () {
              console.log("parent data is: " + this.$parent.value);
        }
    });
 
    const app = new Vue({
        el: '#app',        

        data: function(){

              return {

                     value: "here is parent data"

              }

        }
        mounted: function () {
              console.log("child data is: " + this.$children[0].msg);
        }


    });
</script>

从用法上可以看出$parent 指向了父组件,而$children是个数组,数组中存放的是父组件的子组件。我们首先看看$parent怎么指向到父组件的。

  function initLifecycle (vm) {
    var options = vm.$options;

    // locate first non-abstract parent
    var parent = options.parent;
    if (parent && !options.abstract) {
      while (parent.$options.abstract && parent.$parent) {
        parent = parent.$parent;
      }
      parent.$children.push(vm);
    }

    vm.$parent = parent;
    vm.$root = parent ? parent.$root : vm;

    vm.$children = [];
    vm.$refs = {};

    vm._watcher = null;
    vm._inactive = null;
    vm._directInactive = false;
    vm._isMounted = false;
    vm._isDestroyed = false;
    vm._isBeingDestroyed = false;
  }

 

看这三行代码vm.$parent = parent;     var parent = options.parent;    var options = vm.$options;    $options有parent属性,我们看看$options.parent怎么指向父组件的。还记得我们实例化子组件的地方吗?

  function createComponentInstanceForVnode (
    vnode, // we know it's MountedComponentVNode but flow doesn't
    parent // activeInstance in lifecycle state
  ) {
    var options = {
      _isComponent: true,
      _parentVnode: vnode,
      parent: parent
    };
    // check inline-template render functions
    var inlineTemplate = vnode.data.inlineTemplate;
    if (isDef(inlineTemplate)) {
      options.render = inlineTemplate.render;
      options.staticRenderFns = inlineTemplate.staticRenderFns;
    }
    return new vnode.componentOptions.Ctor(options)
  }

这个options对象里面有parent属性,其值是通过createComponentInstanceForVnode 参数传递过来的。看调用createComponentInstanceForVnode的地方。

  var componentVNodeHooks = {
    init: function init (vnode, hydrating) {
      if (
        vnode.componentInstance &&
        !vnode.componentInstance._isDestroyed &&
        vnode.data.keepAlive
      ) {
        // kept-alive components, treat as a patch
        var mountedNode = vnode; // work around flow
        componentVNodeHooks.prepatch(mountedNode, mountedNode);
      } else {
        var child = vnode.componentInstance = createComponentInstanceForVnode(
          vnode,
          activeInstance
        );
        child.$mount(hydrating ? vnode.elm : undefined, hydrating);
      }
    },

是activeInstance ,这个activeInstance 是在Vue.prototype._update方法中设置的。

var restoreActiveInstance = setActiveInstance(vm);

restoreActiveInstance();

之前我们也分析过这个地方,把父组件设置为了activeInstance, 在渲染出子组件后又恢复原状。到这来我们就找到了$parent怎么指向到了父组件。

父组件怎么把子组件push到$children[]数组中的? 相信你会get到。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值