为啥子组件的挂载钩子刚刚触发时,我们可以获取父组件的整个DOM?
Posted
技术标签:
【中文标题】为啥子组件的挂载钩子刚刚触发时,我们可以获取父组件的整个DOM?【英文标题】:Why we can get the whole DOM of parent component when child component's mounted hook is just triggered?为什么子组件的挂载钩子刚刚触发时,我们可以获取父组件的整个DOM? 【发布时间】:2021-02-19 12:52:27 【问题描述】:前几天刚开始学习vue,前几天一个问题把我搞糊涂了。如下代码:
// inside the parent.vue
<div>
<child-component-a />
<child-component-a />
<div>hello</div>
</div>
...
// inside the child-component-a.vue
<div>child a</div>
...
// inside the child-component-b.vue
<div>child b</div>
...
在我看来,当子组件的mounted
钩子被触发时,dom
应该不可用,以下是我的想法:
// inside the child-component-a.vue
export default
...,
mounted()
// here the DOM is "<div><div>child a</div></div>"
// and not inserted into document yet
// inside the child-component-b.vue
export default
...,
mounted()
// here the DOM is "<div><div>child a</div><div>child-b</div></div>"
// and also not inserted
// inside the parent.vue
export default
...,
mounted()
// here the DOM is "<div><div>child a</div><div>child b</div><div>hello</div></div>"
// and the whole dom has been inserted into document
// so we can manipulate the html element with document APIs
但是,实际上我们可以在 child-a 的挂载钩子被触发时,通过文档 API 获取整个 DOM,为什么?
【问题讨论】:
【参考方案1】:Vue.js 在将其插入 HTML 之前同步构建其虚拟 DOM。为了构建一个元素,它还需要构建子元素。它以预先订购、深度优先的方式执行此操作,这与浏览器构建普通 HTML 的方式非常相似(请参阅https://dom.spec.whatwg.org#trees)。即,为了显示***div
,首先需要知道child-component-a
和child-component-b
是什么。这是渲染顺序:
div
我们看到一个有子元素的 div 组件。我们需要先渲染它们,这样我们才能知道如何在屏幕上绘制这个元素。
a
没有要渲染的子组件,所以我们渲染 a
元素。
b
没有孩子,所以我们渲染 b
。 (注意a
已经被渲染)
div
("hello") 没有子节点,所以我们渲染它的内容(a
和 b
都被渲染了)
div
(***)现在所有子组件都已渲染,我们知道如何绘制它们,我们可以渲染父节点。
[ Vues.js:将此树与现有 DOM 进行比较,只更新需要它的元素。 ]
注意:这稍微简化了。文本内容为text
节点,并相应地呈现。
就个人而言,我认为如果您要使用像 Vue 这样的工具包,您应该尽可能利用它的 API,而不是在不需要时尝试使用低级 API。老实说,我不明白为什么你需要在任何实际场景中使用它,而不仅仅是探索 Vue 的工作原理。如果你正在探索,向你致敬! Vue's API documentation 和 Guide 非常冗长,我建议您坐下来完整阅读它们。对于您遇到的问题,W3C standards documentation(especially on the DOM 和WhatWG)也非常棒,尽管它更具技术性。您不必记住其中的所有信息,只需阅读它,我相信它会在您需要时回来。
【讨论】:
我想可能我表达的不是很清楚,我想知道mounted
钩子到底是什么时候触发的?我认为整个虚拟DOM应该在浏览器渲染之前生成,并且当渲染开始时,父容器div
将首先在浏览器中渲染,然后将每个child
组件的html插入到容器div
一个接一个,所以当child-a
的mounted
钩子被触发时,浏览器中的html
应该是<div><div>child a</div></div>
...然后child-b
...,当所有@987654352 @ 渲染,parent
的 mounted
钩子被触发。
我不认为 vue 是这样渲染的。文档中有一个生命周期图:v3.vuejs.org/guide/instance.html#lifecycle-diagram 如果您正在寻找它。如果你问为什么本地上下文与渲染上下文不同,你应该阅读虚拟 DOM。这里有一个很好的深潜:medium.com/@koheimikami/…以上是关于为啥子组件的挂载钩子刚刚触发时,我们可以获取父组件的整个DOM?的主要内容,如果未能解决你的问题,请参考以下文章