【发布时间】:2017-05-30 10:49:50
【问题描述】:
我知道有很多这样的问题,但这个问题有点不同。我看了reactivity in depth 并认为我对这个主题有一个公平的理解,但我无法理解的一件事是:
tl;dr
为什么当使用currentValue = Object.assign=({}, currentValue, initValue) 初始化而不是直接赋值currentValue = initValue; 时,监视的属性寄存器会发生变化?
我的 vue 组件模型上有一个注册对象,scoreRules
在mounted钩子里,
-
我使用
重新初始化模型的scoreRulesthis.$data.scoreRules = initScoreRules;(
initScoreRules作为道具传入,但我将其声明为本地 为了这个问题的目的,下面的变量)。 观察
scoreRules的变化并在对象发生变化时记录“分数已更改”。
这个 sn-p 显示了这个场景
new Vue({
el: '#app',
data() {
return {
scoreRules: {
type: "number",
minimum: null,
maximum: null
}
}
},
mounted() {
let initScoreRules = {type: "number"};
this.$data.scoreRules = initScoreRules;
this.$watch('scoreRules', ()=>{console.log("score has been changed")}, {deep: true});
}
});
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.js"></script>
</head>
<body>
<div id="app">
<span>Minimum score</span>
<input type="number" name="minimumScore" v-model.number="scoreRules.minimum" />
</body>
</html>
现在,当我在输入中输入内容时,手表不会捕捉到这种变化,并且控制台不会记录任何内容。
如果我现在重新初始化 scoreRules 使用
this.$data.scoreRules = Object.assign({}, this.$data.scoreRules, initScoreRules);
new Vue({
el: '#app2',
data() {
return {
scoreRules: {
minimum: null
}
}
},
mounted() {
let initScoreRules = {};
this.$data.scoreRules = Object.assign({}, this.$data.scoreRules, initScoreRules);
this.$watch('scoreRules', () => {
console.log("score has been changed")
}, {
deep: true
});
}
});
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.js"></script>
</head>
<body>
<div id="app2">
<span>Minimum score</span>
<input type="number" v-model.number="scoreRules.minimum" />
</div>
</body>
</html>
注册更改并将输出记录到控制台。为什么?我怀疑它与 JS 本身的内部有关,但我不确定具体如何。
【问题讨论】:
-
对象是引用类型。这就是为什么您需要使用
Object.assign克隆一个对象,而不是仅仅使用=指向一个现有对象。当您创建一个新对象时,Vue 有机会为该对象及其属性设置其反应环境。 -
我明白了。使用
=进行直接分配将指向一个非反应性对象,因此不会注册对它的更改。现在看来很明显。谢谢。
标签: javascript vue.js