【问题标题】:Vue's v-for with .syncVue 的 v-for 与 .sync
【发布时间】:2026-01-06 14:35:02
【问题描述】:

我有一个表格行,每个行都包含一个选择。希望当“选择”选项更改时,更新父级(包含该表)的数据。

<tbody>

      <tr is="itemComponent"
        v-for="(item, index) in items"
        v-bind:index="index"
        v-bind:item="item"
        v-bind:item-attribute.sync="item.attribute"
      </tr>

</tbody>

然后在 itemComponent 中(接收 item-attribute 作为道具):

<td>
  <select
    v-bind:value="item-attribute"
    v-on:change="$emit('update:item-attribute', $event.target.value)
  >
    <option v-bind:value="true">Yes</option>
    <option v-bind:value="false">No</option>
  </select>
</td>

使用 Vue 的 Chrome 扩展程序,我可以看到 &lt;select&gt;item.attribute 有反应(如果我手动更改它,则选择中的选定选项会更改),并且它还会触发 'update:item-attribute ' 更改时的事件,但它不会更新父级的 item.item-attribute 值。

由于 .sync 只是 v-on:update:item-attribute 的糖,如果我不想使用 .sync,我需要在父组件上写这样的东西:

<tbody>

      <tr is="itemComponent"
        v-for="(item, index) in items"
        v-bind:index="index"
        v-bind:item="item"
        v-bind:item-attribute="item.attribute"
        v-on:update:item-attribute="updateItemAttribute"
      </tr>

</tbody>

methods: {

  updateItemAttribute: function(index,attributeValue) {

    this.items[index].attribute = attributeValue;

  }

}

并且,在子组件上,将 select 中的发出调用更改为(考虑索引为:

v-on:change="$emit('update:item-attribute', index, $event.target.value)

.sync 不应该帮助我避免编写所有这些代码吗?我找不到任何提及它与 v-for 一起使用的内容。

【问题讨论】:

标签: vue.js


【解决方案1】:

答案是事件名称应该是 camelCase,而不是 kebab-case,至少现在是这样。

“至少现在”是因为这绝对是令人困惑的,因为 Vue 的文档明确指出“始终使用 kebab-case 作为事件名称”(请参阅​​ here),但不幸的是,在使用update:eventName 带有 .sync 修饰符。

Vue 的开发人员意识到了这种不一致,并且在这一点上改变代码行为或重写文档是一个悬而未决的问题。到目前为止,.sync 修饰符中的示例使用单个单词的事件名称也无济于事。有关更新,请参阅 https://github.com/vuejs/vuejs.org/issues/1648

所以,目前,当使用 .sync 修饰符时,您应该使用 $emit('update:propNameInCamelCase)`。

不要不要使用$emit('update:prop-name-in-kebab-case)`,否则它将不起作用。

感谢@Jacob Goh 打开 github 问题。

【讨论】: