先说结论:使用vm.$set()实例方法强制更新数组,
数组里面传三个参数:
1.目标数组 2.更新位置(数组索引) 3.更新的值
例如:vm.$set(arr,0,1)意思是将arr数组中下标为0的元素的值更改为1,更改之后强制更新数组.
结论不是重点!重点是明白为什么vue会出现这种情况,从而对Vue的数组检测机制有更清楚的理解
在Vue当中,利用数组数据去渲染页面结构是再寻常不过的事情了.
为什么有时候在Vue当中会出现数组更新检测不到的情况呢?
回答这个问题需要从Vue的数组检测机制讲起.
其实.......vue是不能检测数组和对象变化的......这个是官网原话的截图
所以,如果要想搞清楚底层原理的话,也许这个问题应该先换一种问法:
为什么vue明明不能检测数组变化,但是却可以做到根据数组变化来响应页面的效果呢?
因为实际上,vue不是通过直接检测数组变化来响应页面的,而是通过对调用数组方法,数组重新赋值等操作进行检测从而间接检测数组变化.当这些特定的操作发生的时候,vue就会认为数组发生变化了,从而响应页面.
这可以大致分为两种情况:
1.这些方法会改变数组, vue检测到这些改变数组的方法,直接更新页面
arr.push(),arr.pop(),arr.splice(),arr.reverse(),arr.unshift(),arr.sort()......
2.这些方法不会触发改变数组,而是会得到新数组.不会导致vue更新页面.需要手动把新数组赋值给老数组页面才会更新
arr.filter(),arr.slice(),arr.map(),arr.concat()......
3.vue目前检测不了,无法响应页面的情况
3.1. 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
3.2 当你修改数组的长度时,例如:vm.items.length = newLength
遇到这两种情况可以参考官方文档解决.但是最简单的方法是开头介绍的vm.$set()实例方法
具体代码如下:
<template>
<div>
<ul>
<li v-for="item in list" :key="item">
{{ item }}
</li>
</ul>
<button @click="revBtn">数组翻转</button>
<button @click="sliceBtn">截取前2个</button>
<button @click="updateBtn">更新第一个元素值</button>
</div>
</template>
<script>
export default {
data() {
return {
list: [10,20,30,40,50]
}
},
methods:{
revBtn() {
// 1. 数组翻转可以让v-for更新 -->
this.list.reverse()
},
sliceBtn() {
// 2. 数组slice方法不会造成v-for更新
/* 原因:slice没有改变原始数组,只是从原始数组中获取元素
解决方案: 覆盖原始数组
*/
let newArr = this.list.slice(0, 2)
this.list = newArr
},
updateBtn() {
// 3. 替换元素值,不会造成v-for更新
// this.list[0] = 88
/* 解决方案: this.$set()
参数1: 更新目标结构
参数2: 更新位置
参数3: 更新值
*/
this.$set(this.list, 0, 88)
}
},
}
</script>