簡體   English   中英

Vue.js 意外數據和方法行為

[英]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}]

有任何想法嗎?

控制台.log()

請注意,如果您在最新版本的 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM