vue v-model双向绑定checkbox遇到的坑

今天遇到一个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官方文档有相关说明:https://cn.vuejs.org/v2/guide/reactivity.html

from clipboard
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

之前直接赋值添加属性是非响应式的,是动态为根级别的data字段添加property。vue不认为是正常的property属性,也就是没有生成对应setter(你可以console.log看看新加的属性和其他区别),当更改值时也就不能即时通知watcher,正确渲染组件!

我们知道了以上原理之后,使用下面方式也是ok的(亲测有效)

res.data.forEach(m => {
  m.isChecked = false;
});
that.siteList = res.data;

注意:

先添加属性,再赋值给data中的属性siteList。反之就不行!!!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

织_网

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值