watch+computed实现对表单的每一项的批量修改

305 阅读3分钟

上面动图所展示的,是vue中利用计算属性和watch实现对新增对象的任意数据监听,并修改。而是否修改我这里加了一个变量来控制,体现在修改后续的那个按钮


事情是这样的,上周我正在我的小格子工位上勤勤恳恳的工作,我突然发现我们产品在不远处看着我,我再三确认他确实在看我,我知道来活了。

产品走过来,他说现在会一次性新建很多工单(此部分在这里不讨论),有的值会重复,那能不能做一个批量修改,还要有一个按键可以控制。
我暗自窃喜(监听对象的单个值或者绑定事件一下搞定),产品这时说一个表单可能有20个左右的项

这...,我总不能给左右的表单项加上监听吧。监听对象?那我怎么知道具体是哪一个值变化呢?我果断的说出那句话:技术上很难实现。

产品说:老板对这个功能很重视,他最近心情不好,你看。。

不就是个小小的批量修改!做

首先我们要获取到这个表单对象的新旧值,这个简单,只需要使用watch深度监听一下就好
		我的数据格式:formList:[{},{}]
 	watch:{ 
formList: function (value, oldValue) {
   console.log(value, oldValue) //改变form,打印新旧值,竟然一样
},
deep: true  //深度监听

},

不是说好的能监听到新旧值的呢?

vue官网是这么说的

  好吧,那怎么办呢
  哎?变更对象不会保留,那我使用computed来绑定我的列表数据,然后转化为变更字符串你可以保留吧
 

说干就干

	      computed: {
  newValue() {
    return JSON.stringify(this.formList); //将表格数据序列化
  },
      	watch:{ 
newValue: {
	handler:function (value, oldValue) {
    console.log(value, oldValue) //变了
},
}
deep: true  //深度监听
},

那又怎么知道是具体哪个数据变了呢

 这个很容易想到,请我们的老朋友循环上来耍两下。
 这里确实要耍两下,因为第一次循环用来判断数组里的哪一个表单对象变化了,第二循环用来确定对象里的哪一个值变化了,
 还有一些边界情况考虑下,比如修改后续不该加入批量修改的范围,比如是以新值还是旧值作为循环的依据更合理等等
 所以watch应该是这样写
 
 watch: {
    newValue: {
      handler: function (Val, Val1) {
        let newVal = JSON.parse(Val);//转化为数组
        let oldVal = JSON.parse(Val1);
          newVal.map((item, index) => {
            //循环新数组的每一项对象
            if (
              JSON.stringify(newVal[index]) !== JSON.stringify(oldVal[index])
            ) {
              let newValChild = newVal[index]; //新值的每一项
              let oldValChild = oldVal[index];
              if (newVal.length == oldVal.length) {
                for (let item1 in oldValChild) {
                  if (newValChild[item1] !== oldValChild[item1]) {
                    //如果新值和旧值不一样
                    let sliceList = this.formList.slice(index);
                    if (this.formList[index].editTrue) {
                      //如果可以修改
                      if (
                        item1 == "editTrue" //修改后续的变量不修改
                      ) {
                        return;
                      }else {
                        sliceList.map((itemF, ind) => {
                          if (ind !== 0) {
                            itemF[item1] = newValChild[item1];
                          }
                        });
                      }
                    }
                  }
                }
            }
            }
          });
        
      },
      deep: true,}
      // immediate: true
    },

大概就是这样,这样的写法对性能似乎不是特别友好,希望有大佬能指点指点

代码放在了这里,代码非常的少