数据更新时的一个问题
问题演示:数据发生了改变,但是页面并没有渲染新的数据
<body>
<div id="app">
<div v-for="el in person">
<p>{{el.name}}</p>
<p>{{el.age}}</p>
</div>
<div>
<button @click="update">修改第一个人名信息</button>
</div>
</div>
<script>
new Vue({
el:"#app",
data:{
person:[
{id:1,name:"jessic",age:33},
{id:2,name:"hyomin",age:33},
{id:3,name:"gloria",age:31},
]
},
methods: {
update(){
this.person[0]={id:1,name:"tangxika",age:3};
console.log(this.person[0],111);
}
},
})
</script>
Vue监测数据的原理
1.Vue会通过Object.defineProperty()来劫持data中各个属性的setter,getter,但是不会劫持数组的下标。
2.对象中的数据通过setter实现监视且在创建VM对象时就传入要监测的数据。对象中后追加的属性,Vue默认不做响应式处理,若需要给后添加的属性做响应式需要使用提供的API触发视图更新。
3.数组中的数据监测通过包装数组更新元素的方法,包装时先调用原生对应的方法对数组进行更新,然后重新解析模板进而刷新页面。
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()pop()shift()unshift()splice()sort()reverse()filter()、concat()和slice()。它们不会改变原始数组,但总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组
解决方法:Vue.set(),第1个参数是要操作的对象,第2个参数就是要改变的数组下标或对象的属性名,第3个参数是改变的值。或者创建的Vue组件中使用this.$set(),参数同理。
-
参数:
{Object | Array} target{string | number} propertyName/index{any} value
-
返回值:设置的值。
-
用法:
- 向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向创建VM对象时就传入的对象上添加新属性,因为 Vue 无法探测新增对象的属性
ps:注意目标对象不能是 Vue 实例,或者 Vue 实例的根数据对象,必须是Vue 实例中已有的对象