关于Vue watch 监听对象属性 newValue和oldValue输出同一个对象的一点想法

202 阅读1分钟

考虑如下两段代码:

<template id="my-app">
    <h2>{{obj.message}}</h2>
    <span style="font-size: 24px">旧值:{{oldValue}}&nbsp;&nbsp;新值:{{newValue}}</span>
    <br />
    <button @click="changeMsg">修改msg</button>
</template>
const App = {
    template: "#my-app",
    data() {
        return {
            obj: { message: "Hello World" },
            newValue: "",
            oldValue: "",
        };
    },
    methods: {
        changeMsg() {
            this.obj.message = "Goodbye World";
        },
    },
    watch: {
        obj: {
            handler(newObj, oldObj) {
                this.oldValue = oldObj.message;
                this.newValue = newObj.message;
            },
            deep: true,
        },
    },
    mounted() {
        this.oldValue = this.obj.message;
    },
};

页面预览如下:

image.png

此时点击button执行changeMsg函数后,预期得到旧值为'Hello World',新值为'Goodbye World', 但实际点击后,newObj和oldObj为同一个对象,如下图所示。

image.png

解决这个问题,可以考虑在computed中添加Data属性对obj对象进行深拷贝,再由watch监听Data间接监听obj变化执行handler,如下示代码。

computed: {
    Data() {
       //深拷贝原obj
       return JSON.parse(JSON.stringify(this.obj))			
    }		
},
watch: {
    Data: {
        handler(newObj, oldObj) {
            this.oldValue = oldObj.message;
            this.newValue = newObj.message;
        },
        deep: true,
    }
},

效果如下图所示:

image.png