在 Vue3 和 React 中,响应式数组操作的实现方式和用法存在显著差异,主要体现在响应式机制 、数据变更方式 和API 设计上。以下是具体对比:
1. 响应式机制差异
框架 | 核心原理 | 数组监听方式 |
---|---|---|
Vue3 | 基于 Proxy 的响应式系统 |
自动深度监听数组及其元素的变化(包括索引赋值、push /pop 等方法)。 |
React | 基于不可变数据(Immutable Data)的状态驱动 | 依赖开发者显式返回新引用 (如 setState 或 useState 的更新函数)触发更新。 |
2. 数组操作方式对比
直接修改数组(如 arr[0] = 1
)
-
Vue3
通过
Proxy
自动捕获索引赋值操作,触发响应式更新。javascriptconst list = reactive([1, 2, 3]); list[0] = 100; // 自动触发更新
-
React
直接修改原数组不会触发更新,必须返回新引用:
javascriptconst [list, setList] = useState([1, 2, 3]); // 错误:直接修改原数组,界面不更新! list[0] = 100; // 正确:返回新数组 setList([100, ...list.slice(1)]);
调用数组方法(如 push
、pop
)
-
Vue3
直接调用原生方法(如
push
)会被Proxy
拦截,自动触发更新:javascriptconst list = reactive([1, 2, 3]); list.push(4); // 自动触发更新
-
React
需要手动创建新数组或使用不可变更新模式:
javascriptconst [list, setList] = useState([1, 2, 3]); // 正确:使用新数组 setList([...list, 4]); // 或使用函数式更新 setList(prev => [...prev, 4]);
特殊操作(如修改 length
或 splice
)
-
Vue3
支持通过
splice
或直接修改length
触发更新:javascriptconst list = reactive([1, 2, 3]); list.splice(0, 1); // 正确:触发更新 list.length = 0; // 正确:触发更新
-
React
必须返回新数组引用:
javascriptconst [list, setList] = useState([1, 2, 3]); setList(list.slice(1)); // 正确:返回新数组 setList([]); // 正确:直接替换
3. API 设计差异
操作场景 | Vue3 | React |
---|---|---|
添加元素 | list.push(item) |
setList([...list, item]) |
删除元素 | list.splice(index, 1) |
setList(list.filter((_, i) => i !== index)) |
修改元素 | list[index] = newValue |
setList(list.map((v, i) => i === index ? newValue : v)) |
清空数组 | list.length = 0 |
setList([]) |
4. 设计哲学总结
- Vue3 :隐式自动响应 ,开发者可直接操作原数组,底层通过
Proxy
实现依赖追踪,心智模型更接近原生 JS。 - React :显式不可变更新,强调数据不可变性,每次变更需返回新引用,避免副作用,更利于状态可预测性。
关键结论
- Vue3 通过
Proxy
实现数组的深度响应,操作方式更"原生"。 - React 依赖不可变数据,需开发者主动管理引用变化,确保状态可追踪。
根据项目需求选择:
- 偏好简洁自动 → Vue3
- 需要严格状态控制 → React