Vue中删除数据后列表没更新是怎么回事?

南宫玉戈 阅读 30

我用 Vue 做了个简单的待办列表,添加和编辑都正常,但点击删除后页面上的列表没变化,虽然控制台打印的数组长度确实减少了。是不是响应式出了问题?

我试过用 splice 和 filter,也用了 this.$forceUpdate(),都不行。下面是关键代码:

<template>
  <div v-for="item in todos" :key="item.id">
    {{ item.text }}
    <button @click="removeTodo(item.id)">删除</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      todos: [{ id: 1, text: '学习CRUD' }]
    }
  },
  methods: {
    removeTodo(id) {
      this.todos = this.todos.filter(todo => todo.id !== id);
    }
  }
}
</script>
我来解答 赞 5 收藏
二维码
手机扫码查看
1 条解答
UX-建杰
UX-建杰 Lv1
这个问题挺典型的,我先说结论:你这段代码本身写法没问题,filter 返回新数组赋值的方式是能触发响应式的。

但你说不生效,我猜大概率是下面几个原因:

最可能的情况:数据来源问题

你的 todos 初始值是从哪来的?如果是从 props 传入的,或者是直接从某个非响应式对象赋值过来的,比如:

this.todos = someExternalData  // 这里的 someExternalData 不是响应式的


那后续修改可能不会触发更新。解决办法是在 data 里先初始化为空数组,然后通过 Vue.set 或者在方法里确保赋值的是响应式数据。

次要可能:Object.freeze

如果数据被冻结了,任何修改都不会触发响应式。检查一下有没有用到 Object.freeze()。

关于你试过的方法

splice 和 filter 在 Vue2 里都是响应式的,你用了不行基本就是因为数据本身不是响应式的,而不是方法的问题。this.$forceUpdate() 那是无奈之举,不应该用来解决这种基础问题。



给你一个调试思路,先在 removeTodo 里打个日志:

removeTodo(id) {
console.log('删除前:', this.todos)
this.todos = this.todos.filter(todo => todo.id !== id)
console.log('删除后:', this.todos)
console.log('Vue检测到的todos:', this._data.todos)
}


看看删除前后数据到底变没变,如果确实变了但页面没更新,那就是模板或者 key 的问题。

再或者,你确认一下是不是只有一个组件实例在跑?有时候开发环境热更新会搞出多个实例,你改的是另一个实例的数据。



如果还是不行,把完整的组件代码发出来,我帮你看看具体是哪里坑到了。
点赞
2026-03-16 17:02