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.js3.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,虽然效果达到了,但是这个坑我填了好久,心累。。。
觉得有用请点赞收藏呦~~

Logo

前往低代码交流专区

更多推荐