
在 vue 3 composition api 中,直接对 `form.ranks` 数组调用 `.map()` 得到的普通变量无法自动响应数据变化;需改用 `computed` 声明为计算属性,才能实现依赖追踪与自动更新。
当你使用 @inertiajs/inertia-vue3 的 useForm(或类似表单工具)初始化一个响应式表单对象时,form.ranks 确实是响应式的——但它的响应性仅作用于其自身引用及内部属性的变更。而以下写法:
ranks_options = form.ranks.map(value => value.name);
会立即执行一次 map 并将结果赋值给普通变量 ranks_options,该变量不具备响应式依赖关系,因此后续 form.ranks.push(...) 或 form.ranks[0].name = 'Captain' 都不会触发 ranks_options 更新。
✅ 正确做法:使用 computed 创建一个响应式计算属性:
import { computed } from 'vue';
// 假设 useForm 已从 @inertiajs/inertia-vue3 引入
const form = useForm({
name: null,
ranks: [],
});
function addRanks() {
form.ranks.push({ name: null, id: null });
}
// ✅ 响应式映射:自动追踪 form.ranks 及其每个 item.name 的变化
const ranks_options = computed(() =>
form.ranks.map(item => item.name)
);这样,ranks_options 就成为一个真正的响应式只读 ref(类型为 Ref
立即学习“前端免费学习笔记(深入)”;
- form.ranks 数组长度变化(如 push/pop/splice);
- 某个 item.name 被修改(因 item 是响应式对象,其属性变更可被追踪);
- form.ranks 本身被整体替换(如 form.ranks = [...newRanks])。
⚠️ 注意事项:
- 不要解构 form.ranks 后再操作(如 const { ranks } = form),这会丢失响应性连接;
- 若 ranks 中对象由非响应式来源生成(如 JSON.parse()),需确保它们也被 reactive 或 ref 包裹,否则 item.name 变更无法触发 computed 更新;
- 如需支持双向编辑(例如下拉框绑定 ranks_options[i]),应直接操作 form.ranks[i].name,而非尝试修改 ranks_options —— 因为 computed 返回的是只读视图。
总结:Composition API 中,任何基于响应式数据派生的值,只要需要随源数据自动更新,就必须通过 computed 显式声明。这是响应式系统“依赖自动收集”的核心机制,也是避免手动 watch 或重复 ref 的最佳实践。










