You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue中如何通过contenteditable更新表格行数据?

问题解决:Vue中contenteditable元素数据同步与表格行更新

核心问题是contenteditable元素和Vue数据没有双向绑定:你用{{ }}渲染的只是初始值,修改后不会自动同步到item对象里,所以点击Update时传的还是原始数据。以下是具体解决方案:


1. 把父组件传入的tableData复制到本地响应式变量

Vue的props是只读的,不能直接修改,所以先将props数据转成本地ref:

const localTableData = ref([...props.tableData])

后续的排序、过滤逻辑都基于这个本地变量,而非直接操作props。

2. 给contenteditable元素绑定同步事件

在模板中给p标签添加@input事件,实时将修改内容同步到对应的item字段:

<tbody>
  <tr v-for="item in filteredList" :key="item.id"> <!-- 用item.id作为key更稳定 -->
    <td v-for="field in fields" :key="field">
      <p contenteditable="true" @input="updateField(item, field, $event)">{{ item[field] }}</p>
    </td>
    <button class="btn btn-info btn-lg" @click="UpdateRow(item)">Update</button>
    <button class="btn btn-danger btn-lg" @click="DelteRow(item.id)">Delete</button>
  </tr>
</tbody>

实现同步方法:

const updateField = (item, field, e) => {
  let value = e.target.textContent.trim()
  // 数字类型字段(如total_ex、total_incl)需要转成Number
  if (['total_ex', 'total_incl'].includes(field)) {
    value = Number(value) || 0
  }
  item[field] = value
}

3. 调整排序、过滤逻辑,基于本地数据

修改sortedList和filteredList的计算逻辑,指向本地变量:

const sortedList = computed(() => {
  if (sort.value) {
    return updatedList.value
  } else {
    return localTableData.value
  }
})

const filteredList = computed(() => {
  return sortedList.value.filter((product) => {
    return product.recipient.toLowerCase().includes(searchQuery.value.toLowerCase())
  })
})

// 排序方法也改为操作本地数据的副本
const sortTable = (col) => {
  sort.value = true
  updatedList.value = sortBy([...localTableData.value], col)
}

4. 完善UpdateRow方法

确保使用最新的本地数据,同时添加请求头让后端正确解析JSON:

const UpdateRow = (row) => {
  fetch(`${import.meta.env.VITE_APP_API_URL}/subscriptions/${row.id}`, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(row)
  })
  .then(response => {
    if (!response.ok) throw new Error('更新失败')
    alert('更新成功')
  })
  .catch(err => alert(err.message))
}

额外优化:删除后同步本地数据

修改DelteRow方法,删除接口调用成功后更新本地数据,避免页面刷新:

const DelteRow = (rowId) => {
  fetch(`${import.meta.env.VITE_APP_API_URL}/subscriptions/${rowId}`, {
    method: 'DELETE'
  })
  .then((response) => {
    if (!response.ok) throw new Error('删除失败')
    alert('删除成功')
    localTableData.value = localTableData.value.filter(item => item.id !== rowId)
  })
  .catch((err) => alert(err.message))
}

关键注意事项

  • 永远不要直接修改props,必须复制到本地响应式变量操作。
  • 可根据需求选择@input(实时同步)或@blur(失去焦点时同步)事件。
  • 数字类型字段需要手动转换,因为contenteditable返回的是字符串。
  • 务必添加Content-Type: application/json请求头,否则后端可能无法解析请求体。

内容的提问来源于stack exchange,提问作者Marcello Jardim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 21:18:32