Back To Articles

Vue.js v-for 使用細節

🧑🏻‍💻 Huang, Yung-Hsiang 📅 October 27, 2019

Article Image

在使用 v-for 時有一些要注意的小地方,事先搞清楚這些觀念,在開發時就不會卡關哩。

陣列與物件使用 v-for 的索引不同

v-for 使用在陣列與物件上,索引會有什麼差別呢?

  • 使用於陣列上 → 索引 (key) 為 0, 1, 2
<li v-for="(item, key) in arrayData">
  {{ key }} - {{ item.name }} {{ item.age }} 歲
</li>
  • 使用於物件上 → 索引 (key) 為物件的「屬性」
<li v-for="(item, key) in objectData">
  {{ key }} - {{ item.name }} {{ item.age }} 歲
</li>

GITHUB

就地更新(快速置換)

如果我們在 <input> 上按照順序輸入 1 2 3,接著按下按鈕反轉陣列,會發現 1 2 3 的順序沒有改變,這是為什麼呢?

<li v-for="(item, index) in arrayData">
  {{ index }} - {{ item.name }} {{ item.age }} 歲
  <input type="text" />
</li>
<button class="btn" @click="reverseArray">反轉陣列</button>
// methods 裡的 reverseArray
reverseArray: function () {
    this.arrayData.reverse();
    console.log(this.arrayData);
},

GITHUB

原因是因為 Vue 替換 DOM 元素是使用就地更新(快速置換)的方式。當 Vue 正在更新使用 v-for 渲染的元素列表時,它默認會使用「就地更新」的策略。

在就地更新的狀況下,資料的順序被改變時 Vue 不會因應資料順序而移動 DOM 元素,而是會就地更新每個元素的內容,並且確保它們在每個索引位置上正確渲染。

如果不想要就地更新,而希望要達到反轉,那我們需要給 Vue 提示,讓它能追蹤每個節點的身份,在重複使用的同時也正確地重新排序元素,而這個提示就是為每一項元素加上唯一的 key 值。

加上理想的 key 值

  • 使用 :key 是為了避免就地複用(快速替換),因為我們想要強制替換
  • 理想的 key 值是每個項目都有的唯一值,重複值不能當作 key

在這個例子中,使用 item.ageitem.name 作為 key 都是可以的,但是不能用 :key = "index"

為什麼不行?這邊 index 不是剛好分別是 0, 1, 2 嗎?

這是因為如果用 index 當作唯一值,則在反轉前與反轉後,這些 index 在順序上依然都是 0, 1, 2,而不會變成 2, 1, 0,結果就會變成就地更新的情況了。

所以撰寫 key 的時候,如果有唯一值可以使用,就盡量不要使用 index 這種索引值。

使用 Filter 過濾或產出新內容

使用 v-for 的時候,常常會同時做過濾的行為,亦或是藉此產出想要的資料格式。

例如:將輸入的文字 (filterText) 過濾成畫面想要的內容 (filterArray)。

<input type="text" v-model="filterText" @keyup.enter="filterData" />
<ul>
  <li v-for="(item, key) in filterArray" :key="item.age">
    {{ key }} - {{ item.name }} {{ item.age }} 歲 <input type="text" />
  </li>
</ul>
// methods 裡的 filterData
filterData: function () {
    var vm = this; // 這個 this 指向 Vue 應用程式
    vm.filterArray = vm.arrayData.filter(function (item) {
        console.log(vm.filterText, item.name, item.name.match(vm.filterText));
        return item.name.match(vm.filterText);
    });
},

避免直接操作陣列內容

在 Vue.js 中直接指定陣列並修改資料,雖然這在 console 與 Vue 開發者工具中可以看到更改,但是畫面資料不會跟著變動。

// methods 裡的 cantWork
cantWork: function () {
    this.arrayData[0] = {
        name: '小強',
        age: 99,
    }
    console.log(this.arrayData);
}

如果要操作陣列裡的內容,不能就這樣透過索引去操作,我們必須使用 Vue.set 去執行。

Vue.set(target, key, value)

想要操作或新增原本沒有在 data 裡的資料時,需要使用 Vue.set(針對目標, 索引, 值) 強制將資料寫入 data。

// methods 裡的 cantWork
cantWork: function () {
    Vue.set(this.arrayData, 0, {
        name: '阿強',
        age: 99
    });
    console.log(this.arrayData);
}

純數字的迴圈

除了使用陣列或物件,也可以使用純數字的迴圈。

<ul>
  <li v-for="item in 10">{{ item }}</li>
</ul>

使用 v-for="item in 一個數值",數值是多少,迴圈就會跑幾次。

GITHUB

在 Template 上使用 v-for

如果需要同時使用 v-forv-if 的話,可以藉由在 <template> 標籤上使用 v-for,唯一值 key 綁定在內部元素上的方式。

注意!雖然在官方文件的範例 v-for on a template 當中並沒有綁定 key,但我認為還是應該加上 key,目的是讓 Vue 在演算上能夠區分出元素的唯一性,因此我一樣會做綁定 key 的動作。

<ul>
  <template v-for="item in items">
    <li :key="item.uid" v-if="true">{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫