专业的编程技术博客社区

网站首页 > 博客文章 正文

vue 基础- 指令钩子 update 和 componentUpdated 细节

baijin 2024-10-09 07:56:13 博客文章 6 ℃ 0 评论

前言

《vue 基础》系列是再次回炉 vue 记的笔记,除了官网那部分知识点外,还会加入自己的一些理解。(里面会有部分和官网相同的文案,有经验的同学择感兴趣的阅读)

单独把指令 directive 中 componentUpdated 和 update 拎出来说道下,因为我觉得这些细节值得一说。

这两个钩子函数的介绍

先把官网的介绍再贴遍。希望不太清楚其中区别的同学细读几遍。

update

所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。需要通过前后值得比较来确定不必要的更新。

componentUpdated

指令所在组件的 VNode 及其子 VNode 全部更新后调用。

update 更新的正确判断时机

这是我们的页面模板,里面有自定义的指令 my-directive :

当我们数据 num 发生更新变化的时候(从 1 变为 2),这两个 class 样式会显示什么?

你一定会说两个 class 都是 test-2,但结果却不是这样。

首先,通过 binding 获取的 value 和 oldValue 的值是不同的,分别是变化前后的值:

再看看 vnode 上,两处 class 的取值:

我在 my-directive 自定义指令的 update 方法中,分别通过 vnode 分别输出两个 className 的实际样式名。结果指令所在的节点更新了数据,而子节点却没有。

回过头再看下官网的 update 描述,是不是明白写了?

所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。需要通过前后值得比较来确定不必要的更新。

componentUpdated 的错误理解

我一直错误的以为,componentUpdated 是在所有 vnode 更新完后触发的,但其实又和设想的不一样。

还是和上图例子类似,只是指令钩子换成了 componentUpdated 。

还是看到两处 class 的输出结果不和预期,不是应该都为 2 吗?

解释:

虽然 v-my-directive 指令是写在父模板中,但是写在 mt-badge 组件内。

当 num 更新时,触发当前指令 v-my-directive 所在组件生命周期 udpate 方法,然后再接连触发指令的 updatecomponentUpdated 钩子,但是这个 mt-badge 却还没有被触发它生命周期的 update 方法,这样内部的 num 就没有更新!!这个 num 是在指令 v-my-directive 所在组件的 componentUpdated 结束后,触发到 update 才更新。

每个组件的 update 方法是顺序式的。试想,如果每个组件的 update 没有顺序,那还怎么管理数据流呢?

所以指令触发 componentUpdated 时, v-my-directive 所在组件 VNode 的确更新了,但子组件的 VNode 还保持原样。这样就出现了上面不同养样式名的结果。

你可以试下,如果把 mt-badge 换成一个普通标签,那取到的 ClassName 就一致了,因为不存在父子组件了,大家在同个组件里一起更新完毕的。

指令所在组件的 VNode 及其子 VNode 全部更新后调用。

同样在回头看下官网的表述,是指令所在组件的 vnode 和 指令所在组件的子 vnode,而非子组件的 vnode,是不是这样好理解些?

总结

之前在 vue 基础-过滤器 filter 和指令 directive 示例 说过这块问题,可能,描述的不太清晰,这里再次拿出来讲下,希望如果有类似疑惑的同学能得到解惑。

当然如果有不同看法,希望评论区多交流。

关于我

一位“前端工程师”,乐于实践,并分享前端开发经验。

如果有问题或者想法,欢迎各位评论留言,愿大家共同进步。

关注【前端雨爸】,查阅更多前端技术心得。

Tags:

猜你喜欢

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表