[英]Vue.js unexpected data and method behaviour
我有一個帶有簡單模板的 Vue.js 組件
<div @click="createTargets(2)">
text
</div>
和腳本文件是
export default {
name: 'test',
data() {
return {
targets: [],
};
},
methods: {
createTargets(targetCount) {
this.targets = [];
var emptyTarget = {
id: null,
};
for (var i = 0; i < targetCount; i++) {
var targetToPush = emptyTarget;
targetToPush.id = i;
console.log(targetToPush.id);
this.targets.push(targetToPush);
console.log(this.targets);
}
return {};
},
},
}
當我單擊text
時,我得到 output
0
[{"id":1},{"id":1}]
1
[{"id":1},{"id":1}]
我無法弄清楚為什么會這樣。
我希望
0
[{"id":0}]
1
[{"id":0},{"id":1}]
有任何想法嗎?
請注意,如果您在最新版本的 Chrome 和 Firefox 中記錄對象,您在控制台上記錄的內容是對 object 的引用,這不一定是您在
console.log()
,但它是您打開控制台時 object 的值
不要使用
console.log(obj)
,使用console.log(JSON.parse(JSON.stringify(obj)))
答案真的很簡單,當 object 被分配給一個變量時,它只被初始化一次。 如果將此變量分配給一個新變量,則您將相同的 object 引用分配給一個新變量。 更新 Object1 將更新 Object2,反之亦然。
為了避免這種行為,您可以在使用新的擴展運算符初始化 Object2 時創建 object 的副本:
const targets = [];
const common = { commonProp: 'test' };
for (let i = 1; i <= count; i++) {
const target = { ...common, id: i };
targets.push(target);
}
this.targets = targets;
請注意,您應該避免在循環中改變組件的 state。 即使渲染循環已經過優化並且實際上不會渲染count
次,但最好還是按照示例只改變你的屬性一次。
另請注意,嵌套對象的行為方式相同。 上面的解決方案稱為淺拷貝,相比之下,深拷貝將遞歸地爬取您的 object 以復制子對象/數組。
const common = {
commonProp: { a: 1, b: 2 }
};
const object1 = { ...common, id: 1 };
const object2 = { ...common, id: 2 };
object1.commonProp.a = 2;
console.log(object1); // { commonProp: { a: 2, b: 2 } }
console.log(object2); // { commonProp: { a: 2, b: 2 } }
為避免此問題,您可以使用庫來深度復制對象/數組或創建 class 或工廠 function,每次調用時都會返回新的 object。
// factory
const createTarget = id => ({
commonProp: { a: 1, b: 2 },
id,
});
// class
class Target {
constructor(id) {
this.id = id;
this.commonProp = { a: 1, b: 2 };
}
}
for (let i = 1; i <= count; i++) {
const target = createTarget(i); // or new Target(i);
targets.push(target);
}
我希望這個解釋能幫助你更好地理解這個概念。
祝你好運;)
您可以打印數組值(不是參考):
for (var i = 0; i < targetCount; i++) {
var targetToPush = emptyTarget;
targetToPush.id = i;
console.log(targetToPush.id);
this.targets.push(targetToPush);
// like this (es6 way):
console.log([...this.targets]);
// or like this (old way):
console.log(this.targets.slice());
}
當您使用console.log(this.targets)
時,您將直接打印變量引用,並且它的值將在下一個循環中進行更改,因此它也將在瀏覽器控制台中進行更改。
當您使用console.log([...this.targets])
時,您正在打印該給定循環交互的數組值(而不是引用),即使數組稍后更改,它們也將保持不變。
主要問題,您正在更新參考變量,因此我將始終保留最新數據。 就像下面一樣希望問題會解決
createTargets(targetCount) {
this.targets = [];
for (var i = 0; i < targetCount; i++) {
var targetToPush = {id: null};
targetToPush.id = i;
console.log(targetToPush.id);
this.targets.push(targetToPush);
console.log(this.targets);
}
return {};
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.