为什么用splice修改数组后视图没更新?
我在Vue组件里有个items数组,通过this.items.splice(index,1)删除元素后,页面没变化。但用this.items = []就立刻清空了。试过用Vue.set和this.$set都不行,控制台也没报错,这是为什么啊?
methods: {
removeItem(index) {
// 这样没效果
this.items.splice(index, 1)
// 这样就生效了
// this.items = []
}
}
数据初始化是通过axios获取的接口数据,用data()返回的数组。其他数组方法比如push也能正常更新,唯独splice和直接赋值this.items[index] = newValue不触发更新,搞不懂问题出在哪
不过splice按道理说是能触发更新的,所以问题可能出在数据初始化的时候。如果你的数据是通过axios异步获取的,并且在data里直接声明了一个空数组,那Vue在一开始就没法对这个数组建立完整的响应式监听。
解决办法很简单,你可以试试在数据回来之后,用Vue.set来重新设置整个数组。比如这样:
另外,如果你确定数据结构不会太复杂,也可以用下面这种方式强制重新赋值:
还有一种可能是你的Vue版本问题,早期Vue2.x确实有些响应式的坑,建议确认下是不是Vue版本太老了。我记得Vue2.6之后这类问题基本都修复了。
说个题外话,这种问题调试起来确实头疼,控制台又不报错,页面就是不更新。我之前被这问题折腾了一下午,最后才发现是数据初始化的方式有问题。希望这个回答能帮你少走点弯路。
Vue确实能检测到数组的一些变更方法,比如你提到的push、pop这些都能触发视图更新,但这里有个前提:数组本身必须是被Vue正确追踪的响应式对象。而你的问题很可能是items数组不是通过正确的响应式方式初始化的。
具体来说,如果你是在created或者mounted钩子里直接给this.items赋值了从接口拿到的数据,这种方式会导致items脱离Vue的响应式系统。虽然表面上看它还是个数组,但已经不是响应式的了。
解决办法很简单,在data里先定义好空数组占位,然后在获取数据时用响应式友好的方式更新:
另外补充一点,你说this.$set不管用也是这个原因,因为数组本身的响应式已经失效了,这时候用$set也没用。所以关键是确保数组一开始就进入Vue的响应式系统。
如果已经上线的项目不方便改结构,还有一个稍微hack一点的办法,就是强制重新赋值数组来触发更新:
不过建议还是按第一种方式规范处理,毕竟hack的方式多少有点不优雅。希望这能帮到你!