记 Vue 3 的几个坑

Composition API + Setup Script 可以让我们使用像 Hooks 一样的函数组合写法来书写组件逻辑，和 Hooks 一样具有任意的抽象灵活度。同时对象深响应的能力又摆脱了 Vue 2 必须用 data 浅对象的尴尬问题，可以说是直接摆脱了 Redux、MobX 等等一众工具和它们的捆绑的范式，想怎么写怎么写，又没有 React 的性能问题。

React Hooks are invoked repeatedly every time a component updates. This creates a number of caveats that can confuse even seasoned React developers. It also leads to performance optimization issues that can severely affect development experience. Here are some examples:

• Hooks are call-order sensitive and cannot be conditional.
• Variables declared in a React component can be captured by a hook closure and become "stale" if the developer fails to pass in the correct dependencies array. This leads to React developers relying on ESLint rules to ensure correct dependencies are passed. However, the rule is often not smart enough and over-compensates for correctness, which leads to unnecessary invalidation and headaches when edge cases are encountered.
• Expensive computations require the use of useMemo, which again requires manually passing in the correct dependencies array.
• Event handlers passed to child components cause unnecessary child updates by default, and require explicit useCallback as an optimization. This is almost always needed, and again requires a correct dependencies array. Neglecting this leads to over-rendering apps by default and can cause performance issues without realizing it.
• The stale closure problem, combined with Concurrent features, makes it difficult to reason about when a piece of hooks code is run, and makes working with mutable state that should persist across renders (via useRef) cumbersome.

toRef、toRefs 对源对象赋值导致解绑问题

Vue SFC Playground

// BAD
const { b } = toRefs(a.value)
// GOOD
const b = computed({
get () {
return a.value.b
},
set (x) {
a.value.b = x
}
})

未激活的 keep-alive 组件中子组件生命周期钩子正常触发

Vue SFC Playground