vue组件内手动挂载dom的隐患

302 阅读1分钟

1、手动挂载的隐患

vue组件内,我们有时候会通过js,手动挂载一些其他节点:

image.png

image.png

但这会出现一个什么问题呢,就是当通过修改vue组件模板依赖的属性,或通过调用 $forceUpdate 方法的时候,也即是vue组件重新渲染的时候,会将手动挂载的dom覆盖:

image.png

又恢复到了未挂载的状态。

2、问题的出现与排查

2.1、问题的出现

客户反馈分类这块区域有时候会出现空白的情况:

image.png

通过反复的刷新,发现具体情况是:

先空白(还未初始化)-> 出现数据(首次渲染)-> 重新空白(未知原因)

但通过打断点发现,渲染的方法确实进入过,且dom、数据都是有的,并没有什么异常:

image.png

而且通过 mounted 钩子确定组件并没有反复挂载的情况。而且即便有,也会在组件挂载后,走手动挂载dom的逻辑的。

2.2、问题的定位

通过排查发现,重新空白的dom结构,跟原始的、未手动挂载的dom结构一致:

image.png

image.png

故怀疑是反复执行 render 函数的原因。

通过打断点发现,render函数确实被调用了几次:

image.png

而问题的原因就是本文第一点提到的,因为触发了重新渲染,导致手动挂载的dom被覆盖掉了。

3、解决方案

因为这是vue触发dom刷新导致的,所以我们可以利用 updated 钩子( 通过调用 $forceUpdate 方法触发的刷新也会执行这个钩子)。

把原先只在 mounted 钩子内执行的手动挂载 dom 的逻辑,也添加到 updated 钩子执行。

但要注意的是,并非所有的刷新都需要触发重新挂载,所以 updated 钩子的函数需要另外做些限制:

image.png