发表于2020-08-20
今天遇到一个vue诡异的数据绑定问题,下面我给大家分享一下我解决问题思路和方式,以及为什么要这样。
使用vant的checkbox组件时无法使用v-model来双向绑定选中状态!但是重新打开checbox所在的pop弹窗,又能显示之前操作的最新的选中值,如果不关闭之后重新打开,始终都不更新,感觉好像没有没有反应一样。
html代码:
<div v-for="item in siteList" :key="'site-'+ item.id" class="list-site-item" @click="toggleSiteItem(item)"> <div class="site-name">{{ item.siteName }}{{item.siteCode}}</div> <div class="site-other-info"> <div class="site-check-cont"> <van-checkbox :name="item.id" v-model="item.isChecked" shape="square"> </van-checkbox> </div> <div class="site-other-right"> <div class="site-info-item"> <div class="site-info-label">区域:</div> <div>{{ item.areaName }}</div> </div> <div class="site-info-item"> <div class="site-info-label">省份:</div> <div>{{ item.province }}</div> </div> <div class="site-info-item"> <div class="site-info-label">二级单位:</div> <div>{{ item.companyName }}</div> </div> </div> </div> <van-divider /> </div>
为了保持接口的kiss,后台接口不返回是否选中“isChecked”这个字段(为了让接口简单,一般接口都不返回后台没有存储的属性)。
原来的js代码:
searchActiveSites({ keywords: that.searchSiteKeywords }).then(res => { that.siteList = res.data; that.siteList.forEach(m => { m.isChecked = false; }); that.loadSitefinished = true; });动态的加上属性“isChecked”。
切换选中状态:
let that = this; // that.$refs.checkboxes[index].toggle(); // debugger; that.siteList.forEach(m => { if (m.id === item.id) { m.isChecked = !m.isChecked; } });
searchActiveSites({ keywords: that.searchSiteKeywords }).then(res => { that.siteList = res.data; if (res && res.data.length > 0) { // Vue.set 等同 this.$set that.siteList.forEach(m => { that.$set(m, 'isChecked', false); }); } // 诡异问题,不能v-model双向绑定,需要重新打开pop // that.siteList.forEach(m => { // m.isChecked = false; // }); that.loadSitefinished = true; });使用$set方法添加对象属性!问题就解决了!
原来vue官方文档有相关说明:
之前直接赋值添加属性是非响应式的,是动态为根级别的data字段添加property。vue不认为是正常的property属性,也就是没有生成对应setter(你可以console.log看看新加的属性和其他区别),当更改值时也就不能即时通知watcher,正确渲染组件!
我们知道了以上原理之后,使用下面方式也是ok的(亲测有效)
res.data.forEach(m => { m.isChecked = false; }); that.siteList = res.data;先添加属性,再赋值给data中的属性siteList。反之就不行!!!