我们在父组件中通过$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到。