随笔:记录一个Vue3 watch监听对象时newValue和oldValue相等的问题

问题

今天遇到一个问题:在处理一个list时,要监听list中一个表单值的变化,同时对list其中的项进行回写,如果不判断新旧值相等的问题,就会造成无限循环调用watch回调,所以需要判断oldValue !== newValue 才可以进行对list子项写入的操作。
但是由于监听的是一个表单对象,所以oldValue和newValue永远相等

监听subAuditItemList里Item._formValue 给 Item.extraSubmitParams 赋值

    watch(
        () => subAuditItemList.map(item => item._formValue),
        (newValues, oldValues) => {
            newValues.forEach((newValue, index) => {
                const item = subAuditItemList[index];
                // 检查是否有变化,只有在变化时才更新
                console.log(JSON.stringify(item._formValue) !== JSON.stringify(oldValues[index]));   // 永远为false
                // if (JSON.stringify(item._formValue) !== JSON.stringify(oldValues[index])) {
                //     root.value.$set(item, 'extraSubmitParams', {
                //         ...item.extraSubmitParams,
                //         ...newValue,
                //     });
                //     // item.extraSubmitParams = {
                //     //     ...item.extraSubmitParams,
                //     //     ...newValue,
                //     // };
                // }
            });
        },
        {
            deep: true
        }
    );

原理

Vue监听值类型不会出现新旧值打印相等的问题,只有在监听引用类型的时候会遇到新旧相等的问题。

Vue官方的解释是:在变更(不是替换)对象或数组时,新值与旧值相同,因为他们指向同一数组或对象,Vue不会保留变更前值的副本。

解决方案

通过computed对引用类型cloneDeep,watch这个计算属性即可。

原理:深拷贝watch的值内存地址有更新,和watch一个值类型的数据没区别。

   const formValueList = computed(() => {
        return JSON.parse(JSON.stringify(subAuditItemList.map(item => item._formValue)));
    });
    watch(
        formValueList,
        (newValues, oldValues) => {
            console.log(JSON.stringify(newValues), JSON.stringify(oldValues));
        },
        {
            deep: true
        }
    );
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容