Vue watch() 输出相同的 oldValue 和 newValue

Pow*_*ile 13 javascript vue.js

在做我的前端 Vue 项目时,当元素被推入列表中时,我需要执行某些步骤data。但是,当我将一些初始值推入 中的列表时mounted()console.log()相应的 中和参数值watch()输出相同的值。newValoldVal

JavaScript/Vue 代码:

let app = new Vue({
    el: "#app",
    data: {
        testList: [],
    },
    mounted: function() {
        this.testList.push('a');
        this.testList.push('b');
        this.testList.push('c');
    },
    watch: {
        testList: {
            handler: function(newVal, oldVal) {
                console.log("new", newVal);
                console.log("old", oldVal);
            },
        },
    }
});
Run Code Online (Sandbox Code Playgroud)

控制台日志信息: 控制台日志信息

  1. 为什么 和newVal具有oldVal相同的值?
  2. 为什么该函数没有watch()被执行三次(因为我在 中推送了三次mounted())?

equ*_*qui 10

此外,如果有人在观察嵌套属性更改并使用标志deep: true时遇到此问题,则预计 newValue 和 oldValue 相同(参考)。

为了解决这个问题,您可以添加计算属性来包装应监视的数据对象,并监视计算属性的更改。

export default {
name: 'ExampleComponent',
data () {
    return {
        exampleObject: {
            name: 'User',
            email: 'Email'
        }
    }
},

computed: {
    computedObjectToBeWatched () {
        return Object.assign({}, this.exampleObject)
    }
},

watch: {
    computedObjectToBeWatched: {
        deep: true,
        handler (value, oldValue) {
            if (value.name !== oldValue.name) {
                console.log('changes occured')
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 并熟悉 Vue 3 / Composition API 语法中的此解决方案。`const usedToBeWatched = ref([]);` const WatchedCompulated = Computed(() => StructuredClone(toRaw(usedToBeWatched.value)));` `watch(watchedCompulated, (newVal, oldVal) => { console.log( 'watchedCompulated', newVal, oldVal) }));` (2认同)

GMK*_*ain 7

我改变了两件事

  1. 在手表中克隆
  2. 添加计算的

现在效果很好。

console.clear();

let app = new Vue({
    el: "#app",
    data: {
        testList: ['old'],
    },
    mounted: function() {
        this.testList.push('a');
        this.testList.push('b');
        this.testList.push('c');
    },
    watch: {
        testListClone: { //<-- Edited
            handler: function(newVal, oldVal) {
                console.log("new", newVal);
                console.log("old", oldVal);
            },
        },
    },
  computed:{  //<-- Added
    clonedItems: function(){
       return JSON.parse(JSON.stringify(this.testList))
    }
  }
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>

<div id="app"></div>
Run Code Online (Sandbox Code Playgroud)

  • 凉爽的!这有效。然而我相信这个答案中有一个拼写错误:在“compulated”中,变量被称为“clonedItems”,但在“watch”中,它被称为“testListClone” 。只有当这两个名称相同时,代码才能运行。您能否更改拼写错误并修复“计算”中的缩进问题,以便我可以将其标记为答案?谢谢 (2认同)