Props 与 useSetup 边界
这个页专门验证一个问题:父组件修改 props 后,子组件里依赖 props 的局部值到底哪些还能动态变化。 如果把依赖解构 props 的局部直接搬进一次性的 useSetup,它会退化成首帧快照。
还有一个容易混淆的点:useSetup 首次执行里创建的 watch、watchEffect、createEffect 不属于每轮 render 都会重建的 render-scope。它们会挂在组件实例的持久 hook scope 上,只在组件卸载时统一清理。
父组件 props.count
当前 query transfer
trim().toUpperCase()TRANSFER
当前 count2
1. 当前安全行为:render 期直接读取解构 props
这个分支不进一次性 setup。父 props 改变时,组件重新求值,所以展示值会跟着变。
normalizedTRANSFER
summaryTRANSFER x 2
moderender 期直接读取解构 props
2. 假设把 Transfer 风格的 props 初始化整体搬进一次性 useSetup
这里手写 useSetup 模拟错误 hoist。searchConfig、searchValueRef、pageRef 都只取首帧。
searchConfig.defaultValueTRANSFER
searchValueRef.valueTRANSFER
pageRef.value2
mode手写 useSetup,一次性捕获解构 props
3. 可以放进 useSetup 的安全写法:保留 props 对象,用 computed 读取
这更接近 Vue 3 setup + props 对象的模式。computed 依赖 props 对象本身,所以仍会动态更新。
normalized.get()TRANSFER
summary.get()TRANSFER x 2
modeuseSetup 内改用 props 对象 + computed
4. 新行为:放进 useSetup 后继续用解构 props,只要在 computed 里读取就还能保持响应
这一块现在依赖编译器改写。query 和 count 会被重写成隐藏 props 对象读取,所以 computed 仍会跟着父 props 变化。
normalized.get()TRANSFER
summary.get()TRANSFER x 2
modeuseSetup 内用解构 props + computed,编译器会改写为隐藏 props 读取
观察重点: 1. 第 1 块会随父 props 一直变化。 2. 第 2 块模拟“把 props 相关初始化错误放进 useSetup”的结果,会停在初始值。 3. 第 3 块说明 props 不是绝对不能进 setup,关键是要保留 reactive props 对象,并在 computed 或 watch 里读取。 4. 第 4 块说明现在顶层解构 props 也不是天然不安全,只要读取发生在 computed 里,编译器会把它改写回隐藏 props 访问。 5. setup 内创建的 watch、watchEffect、createEffect 会跟着组件实例一起存活;如果它们像 render-scope 一样在每次父组件更新后被销毁,后续 props 变化就会出现“第一次能跑,第二次失活”的假象。
Nested 解构边界
这里专门验证更复杂的嵌套解构:对象里再套对象、数组项默认值、别名,以及整个参数默认值。
nested counts
options.query nested transfer
options.meta.labeldeep-live
counts[0]3
counts[1]5
5. Nested 解构 + computed:对象/数组/默认值/别名都会被改写成隐藏 props 读取
这里覆盖 options.query、options.meta.label、counts[0]、counts[1],同时允许整个参数或子层级缺省。
normalized.get()NESTED TRANSFER
total.get()8
summary.get()deep-live:NESTED TRANSFER x 8
tuple.get()3-5
modenested 解构 + 默认值/别名 + computed,仍然保持响应式
6. Nested 解构 + 一次性快照:即使编译器能改写读取,先算成普通值还是会冻结
边界没有消失。真正危险的是在 useSetup 首次执行时就把 nested 解构结果拍平成普通字符串或数字。
normalizedNESTED TRANSFER
total8
summarydeep-live:NESTED TRANSFER x 8
tuple3-5
modenested 解构后如果先算成一次性快照,仍然只会取首帧
Nested 观察重点: 1. 第 5 块现在覆盖更复杂的解构:嵌套对象、数组项、默认值、别名、整个参数默认值。 2. 关闭 options、meta 或 counts 传入后,第 5 块会退回对应默认值,但仍然保持响应式。 3. 第 6 块说明编译器只保证“读取时”还能回到 reactive props;如果你在 useSetup 首次执行里先算出普通快照,动态性还是会丢。