shouldUpdateComponent 由父组件在 patch 子节点时调用,当发现旧子组件实例存在(n1.component 存在)即立即触发,传入新旧 VNode;默认浅比较 props、children、slots 三者引用,任一变化则返回 true 触发更新,全等才返回 false 跳过。

Vue 不是靠“识别”来决定是否更新组件,而是靠 shouldUpdateComponent 这个守门函数,在 patch 开始前就做出跳过或继续的决策。它不参与 diff,只做一次浅比较,返回 false 就直接跳过整个子组件的更新流程。
shouldUpdateComponent 是谁调用的?
它在父组件 patch 子节点时、发现旧子组件实例已存在(n1.component 存在)后立即触发,传入新旧 VNode 作为参数。不是组件内部方法,也不依赖 this,纯函数形式,运行在父组件上下文中。
默认比对哪些内容?
Vue 3 默认对以下三项做浅比较(=== 或 Object.is):
- Props:逐 key 比较新旧 props 对象中各字段的值引用是否一致
-
Children:直接比较
n1.children === n2.children,不 deepEqual -
Slots:比较
n1.slots === n2.slots,注意函数式插槽每次渲染都会生成新函数,容易误判为变化
只要其中任一项目引用不同,就返回 true,表示需更新;全部相同才返回 false,跳过该子组件。
立即学习“前端免费学习笔记(深入)”;
什么情况下会误触发更新?
常见于未注意引用稳定性的写法:
- 模板中写
:config="{ theme: 'dark' }"—— 每次渲染都新建对象,props 引用总变 - 使用
v-for但没设key或 key 不唯一 —— 导致 children 顺序错乱,VNode 复用失败 - 插槽内容含内联函数,如
<template><button> doX()"></button></template>—— slots 引用每次不同
如何自定义判断逻辑?
可在 defineComponent 中显式声明:
{<br> shouldUpdateComponent: (prevVNode, nextVNode) => {<br> // 忽略仅用于调试的 prop<br> if (prevVNode.props?.debugId === nextVNode.props?.debugId) {<br> return false;<br> }<br> // 或只在特定状态变更时更新<br> return prevVNode.props?.status !== nextVNode.props?.status;<br> }<br>}
注意:不能在 setup 返回对象里定义,必须通过组件选项方式声明。


















