如何理解”在 mounted 中使用 vm.$nextTick “

背景

最近在重新复习 vue 的源码,对官方文档中一句话产生疑问,原话:

注意mounted不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在mounted内部使用vm.$nextTick

疑问

虽然以前做项目写代码的时候都会谨记在mounted中(如果要对DOM操作)加入 $nextTick,但现在仔细想想好像多此一举。

  1. 原话的“子组件也一起挂载”中的“挂载”指的就是mounted,那么除了异步组件还有什么条件会出现该情况呢?看源码后我的理解是:patch是深度递归、同步的一个过程,理论上父组件mounted了子组件也必定已经触发了mounted,不会出现上述的情况。
  2. 排除掉异步组件,读源码可知在patch过程的最后一步(这之前已经生成了用于插入文档的vnode.elm,且已执行了真实的DOM元素插入语句),会调用invokeInsertHook触发所有组件对应的mounted钩子(从子到父)。那理论上在mounted钩子中我们直接去操作对应生成的DOM应该是绝对安全的没错吧?DOM的修改不是同步的吗?
  3. 至于后面文档提到如果要等整个视图都渲染完毕,加上$nextTick即可解决,强调是只是如果要等整个视图真正渲染到显示屏上的时候才做额外处理是吧?因为渲染(render)过程是异步的?

补充

当然在挂载后手动去操作数据,然后立马操作DOM是不符合预期的,因为update是一个异步的过程。以上的疑问仅仅是针对初始的挂载操作。可能我对文档描述本身和源码的阅读存在误解,望指出。

阅读 6.3k
1 个回答

不敢说正确,我跟你探讨一下啊。

  1. 我认为只有异步组件才会出现这种情况,同步组件没有这个问题;
  2. 如果不是异步组件的话,我认为你在父组件的mounted里直接操作子组件的DOM是没有问题的,理由如你所说;
  3. 这说的还是异步组件,如果你想操作异步子组件的DOM的话,则需要在父组件的mounted里面$nextTick里做,这时候可以保证部分异步子组件的渲染已结束,但并不能保证所有的,例如某子组件加了setTimeout要10秒之后才渲染DOM树,那么你$nextTick也是没有用的,对吧?
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题