- 如果一个属性你在data的时候没有初始化,那么后面不能直接在已经创建的实例上动态添加新的属性,否则这个新添加的属性就不会是响应式的。
ar vm = new Vue({
data:{
a:1
}
})
// `vm.a` 是响应的
vm.b = 2
// `vm.b` 是非响应的
- 通过请求拿到的原始数据,如果你想给它动态添加一个属性,正常情况下它也不会是响应式的,比如原始数据如下
{
"status": 200,
"message": "",
"cartList": [
{
"shopTitle": "寻找田野",
"shopId": 75960,
"goodsList": [
{
"id": 73835,
"img": "http://dummyimage.com/90x90/f27988",
"number": 2,
"price": 75,
"sku": "全网通,玫瑰金,3+32G",
"title": "VIVO-Y66 全网通/移动版 3+32GB"
},
{
"id": 75572,
"img": "http://dummyimage.com/90x90/79abf2",
"number": 2,
"price": 31,
"sku": "全网通,香槟金,3+32G",
"title": "VIVO-Y66 全网通/移动版 3+32GB"
}
]
},
{
"shopTitle": "猫咪森林",
"shopId": 51336,
"goodsList": [
{
"id": 57979,
"img": "http://dummyimage.com/90x90/cef279",
"number": 9,
"price": 44,
"sku": "全网通,玫瑰金,3+32G",
"title": "VIVO-Y66 全网通/移动版 3+32GB"
}
]
},
{
"shopTitle": "老爹果园",
"shopId": 94835,
"goodsList": [
{
"id": 44271,
"img": "http://dummyimage.com/90x90/f279f2",
"number": 5,
"price": 105,
"sku": "全网通,香槟金,3+32G",
"title": "VIVO-Y66 全网通/移动版 3+32GB"
},
{
"id": 81594,
"img": "http://dummyimage.com/90x90/79f2ce",
"number": 8,
"price": 39,
"sku": "全网通,玫瑰金,3+32G",
"title": "VIVO-Y66 全网通/移动版 3+32GB"
}
]
}
]
}
通过axios拿到数据通过vue渲染到dom上
<div class="js-shop-list shop-list" v-for="(shop,index) in list">
<ul class="js-list block block-list block-list-cart border-0">
<li class="block-item block-item-cart" v-for="(good,goodIndex) in shop.goodsList">
<div class="check-container" @click="checkedGood(good)">
<span class="check" :class="{checked:good.checked}"></span>
</div>
</li>
</ul>
</div>
let app = new Vue({
el: '#app',
data: {
list: null
},
created(){
this.getLists()
},
methods: {
getLists(){
axios.get(url.cartList)
.then((res)=>{
this.list = res.data.cartList
this.list.forEach(shop => {
shop.goodsList.forEach(good=>{
good.checked = true
})
});
})
},
checkedGood(good){
good.checked = !good.checked
console.log(good.checked)
}
},
})
显示效果如下:
因为原始数据里面没有checked这个属性,所以你直接将原始数据赋给了data里的list,它就等同于第一条的例子,在实例创建完后直接给good加一个checked属性,这时候你点击选中按钮通过checkedGood方法更改选中状态,你会发现虽然后台显示的值已经在true和false之间切换了,但是vue里的数据和视图显示并没有改变,也就是没有发生响应式。
点击选中按钮,控制台打印出每次的checked的值都在变,但是视图显示一直是选中状态,不管你怎么点击按钮都是选中状态,视图没有改变
vue里的数据也一直没有变化过
针对上面的两个问题有两种解决办法:
- 针对第一中简单的数据添加可以直接使用实例的set方法
this.$set(this.someObject,'b',2)
- 针对第二种复杂结构的原始数据,可以先对原始数据操作最后再赋值给vue实例
getLists(){
axios.get(url.cartList)
.then((res)=>{
//将原始数据res.data.cartList赋值给一个变量
let list = res.data.cartList
//然后对这个变量直接进行动态属性添加
list.forEach(shop => {
shop.goodsList.forEach(good=>{
good.checked = true
})
});
//最后再赋值给实例里的list
this.list = list
})
}
这样就可以实现数据和视图的同步更改了,也就是可以响应了