vue双向绑定有时候不生效处理办法
vue双向绑定有时候不生效处理办法问题:当我们给响应式的对象新增属性时,新增的属性并不会显示到页面中;对于响应式的数组,增加元素、修改数组长度时,数组的这些变化也不会反映到页面中<template><div>{{obj}}{{arr}}<button @click="change">Click me!</button></div><
vue双向绑定有时候不生效处理办法
问题:当我们给响应式的对象新增属性时,新增的属性并不会显示到页面中;对于响应式的数组,增加元素、修改数组长度时,数组的这些变化也不会反映到页面中
<template>
<div>
{{obj}}
{{arr}}
<button @click="change">Click me!</button>
</div>
</template>
<script>
export default {
data() {
return {
obj: {
a:'你真是个小可爱'
},
arr:['奥']
}
},
methods: {
change(){
this.changeObj();
this.changeArr();
console.log(this.obj,this.arr)
},
changeObj() {
this.obj.b = '是的呢'//虽然你写了,但是页面我就不变,就是玩
},
changeArr(){
this.arr[3] = '给' //虽然你写了,但是页面我就不变,就是玩
}
},
}
</script>
不生效原因:对象obj及其属性a,数组arr在vue初始化时已处理成响应式的,即当我们改变对象obj的值或属性a的值时,会触发其在页面上的更新,但是当页面加载完成后,新增的属性b就不是响应式的,虽然通过打印this.obj可以看出对象obj上确实增加了属性b,但是由于b不是响应式的,所以新增的属性不会体现在页面上。
对于数组arr也存在类似的问题,当我们通过索引值添加元素或更改数组长度时,数组本身是发生变化了,但是没有及时体现在页面上。
解决方法:
1.this.$set(‘绑定对象’,‘key’,‘value’)
原理可参考这篇博客this.$set源码分析
案例:这个是我做一个项目时,有这样一个需求,根据一个月多少天计算工资,每天的工资是需要自己手录的,这就需要在每个日期后面循环一个input框,并且动态计算总工资,输入超过24小时的以24小时计算,这里贴出部分代码
<el-table :data="tableData" height="250" border style="width: 100%;">
<el-table-column prop="empName" label="员工名称" width="180"></el-table-column>
<el-table-column prop="name" label="合作公司" width="180"></el-table-column>
<el-table-column prop="date" label="工时统计日期"></el-table-column>
<el-table-column fixed="right" label="工时录入" width="200" height="38">
<template slot-scope="scope">
<input
@change="handleBlur(scope.row.id)"
type="number"
min="0"
max="24"
onkeyup="value=value.replace(/[^\d.]/g, '').replace(/\.{2,}/g, '.').replace('.', '$#$').replace(/\./g, '').replace('$#$', '.').replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3').replace(/^\./g, '')"
placeholder="请输入数字"
class="gongshi"
v-model="solar['gongshi'+ scope.row.id]"
/>
<span></span>
</template>
</el-table-column>
</el-table>
export default {
data() {
return {
solar:{}
}
},
}
handleBlur(id) {
if (this.solar['gongshi' + id] > 24) {
//this.solar['gongshi' + id] = 24//这样写页面不改变
this.$nextTick(() => {
this.$set(this.solar, `gongshi${id}`, '24')//这样写就好了
})
}
this.solar['gongshi' + id] = this.solar['gongshi' + id]
.toString()
.replace(/[^\d.]/g, '')
.replace(/\.{2,}/g, '.')
.replace('.', '$#$')
.replace(/\./g, '')
.replace('$#$', '.')
.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
.replace(/^\./g, '')//两位小数
this.moneyTotal = 0
for (let i in this.solar) {//改变某一个输入框的值就重新计算总价
this.moneyTotal += Number(this.solar[i] || 0) * this.temp.hourSalary
}
this.moneyTotal = this.moneyTotal.toFixed(2)
},
2.this. f o r c e U p d a t e ( ) 这 个 我 偶 尔 会 用 , 据 说 这 个 不 太 好 , 咱 也 不 敢 问 , 咱 也 不 敢 说 , 咱 就 听 着 就 完 事 了 原 理 : 手 动 通 知 V u e . j s 实 例 重 新 渲 染 。 3. 其 实 我 遇 到 过 上 面 两 种 都 没 有 更 新 数 据 的 情 况 , 上 面 的 是 在 新 建 一 个 列 表 , 在 编 辑 列 表 的 时 候 , 无 论 我 用 t h i s . forceUpdate() 这个我偶尔会用,据说这个不太好,咱也不敢问,咱也不敢说,咱就听着就完事了 原理:手动通知Vue.js实例重新渲染。 3.其实我遇到过上面两种都没有更新数据的情况,上面的是在新建一个列表,在编辑列表的时候,无论我用this. forceUpdate()这个我偶尔会用,据说这个不太好,咱也不敢问,咱也不敢说,咱就听着就完事了原理:手动通知Vue.js实例重新渲染。3.其实我遇到过上面两种都没有更新数据的情况,上面的是在新建一个列表,在编辑列表的时候,无论我用this.set(‘绑定对象’,‘key’,‘value’)还是this.$forceUpdate(),都不管用,百思不得其解,最后放弃这两种方法,改用
handleEditBlur(id) {
this.esolar['gongshi' + id] = this.esolar['gongshi' + id]
.toString()
.replace(/[^\d.]/g, '')
.replace(/\.{2,}/g, '.')
.replace('.', '$#$')
.replace(/\./g, '')
.replace('$#$', '.')
.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
.replace(/^\./g, '')
if (this.esolar['gongshi' + id] > 24) {//超过24置为24,this.$set以及forceupdate均不起作用(数据改变了页面不变)
this.esolar['gongshi' + id] = 24
this.$refs['gongshi' + id].value = 24
}
this.moneyTotal = 0
for (let i in this.esolar) {
this.moneyTotal += Number(this.esolar[i] || 0) * this.temp.hourSalary
}
this.moneyTotal = this.moneyTotal.toFixed(2)
},
没错,就是 this.$refs[‘gongshi’ + id].value,虽然效果达到了,但是这个坑我填了好久,心累。。。
觉得有用请点赞收藏呦~~
更多推荐
所有评论(0)