Vue.js v-for 使用細節
在使用 v-for 時有一些要注意的小地方,事先搞清楚這些觀念,在開發時就不會卡關哩。
陣列與物件使用 v-for 的索引不同
v-for 使用在陣列與物件上,索引會有什麼差別呢?
- 使用於陣列上 → 索引 (key) 為 0, 1, 2
1<li v-for="(item, key) in arrayData"> 2 {{ key }} - {{ item.name }} {{ item.age }} 歲 3</li> 4
- 使用於物件上 → 索引 (key) 為物件的「屬性」
1<li v-for="(item, key) in objectData"> 2 {{ key }} - {{ item.name }} {{ item.age }} 歲 3</li> 4
就地更新(快速置換)
如果我們在 <input>
上按照順序輸入 1 2 3
,接著按下按鈕反轉陣列,會發現 1 2 3
的順序沒有改變,這是為什麼呢?
1<li v-for="(item, index) in arrayData"> 2 {{ index }} - {{ item.name }} {{ item.age }} 歲 3 <input type="text" /> 4</li> 5<button class="btn" @click="reverseArray">反轉陣列</button> 6
1// methods 裡的 reverseArray 2reverseArray: function () { 3 this.arrayData.reverse(); 4 console.log(this.arrayData); 5}, 6
原因是因為 Vue 替換 DOM 元素是使用就地更新(快速置換)的方式。當 Vue 正在更新使用 v-for
渲染的元素列表時,它默認會使用「就地更新」的策略。
在就地更新的狀況下,資料的順序被改變時 Vue 不會因應資料順序而移動 DOM 元素,而是會就地更新每個元素的內容,並且確保它們在每個索引位置上正確渲染。
如果不想要就地更新,而希望要達到反轉,那我們需要給 Vue 提示,讓它能追蹤每個節點的身份,在重複使用的同時也正確地重新排序元素,而這個提示就是為每一項元素加上唯一的 key 值。
加上理想的 key 值
- 使用
:key
是為了避免就地複用(快速替換),因為我們想要強制替換 - 理想的 key 值是每個項目都有的唯一值,重複值不能當作 key
在這個例子中,使用 item.age
與 item.name
作為 key 都是可以的,但是不能用 :key = "index"
。
為什麼不行?這邊 index 不是剛好分別是 0, 1, 2 嗎?
這是因為如果用 index 當作唯一值,則在反轉前與反轉後,這些 index 在順序上依然都是 0, 1, 2,而不會變成 2, 1, 0,結果就會變成就地更新的情況了。
所以撰寫 key 的時候,如果有唯一值可以使用,就盡量不要使用 index 這種索引值。
使用 Filter 過濾或產出新內容
使用 v-for
的時候,常常會同時做過濾的行為,亦或是藉此產出想要的資料格式。
例如:將輸入的文字 (filterText) 過濾成畫面想要的內容 (filterArray)。
1<input type="text" v-model="filterText" @keyup.enter="filterData" /> 2<ul> 3 <li v-for="(item, key) in filterArray" :key="item.age"> 4 {{ key }} - {{ item.name }} {{ item.age }} 歲 <input type="text" /> 5 </li> 6</ul> 7
1// methods 裡的 filterData 2filterData: function () { 3 var vm = this; // 這個 this 指向 Vue 應用程式 4 vm.filterArray = vm.arrayData.filter(function (item) { 5 console.log(vm.filterText, item.name, item.name.match(vm.filterText)); 6 return item.name.match(vm.filterText); 7 }); 8}, 9
避免直接操作陣列內容
在 Vue.js 中直接指定陣列並修改資料,雖然這在 console 與 Vue 開發者工具中可以看到更改,但是畫面資料不會跟著變動。
1// methods 裡的 cantWork 2cantWork: function () { 3 this.arrayData[0] = { 4 name: '小強', 5 age: 99, 6 } 7 console.log(this.arrayData); 8} 9
如果要操作陣列裡的內容,不能就這樣透過索引去操作,我們必須使用 Vue.set 去執行。
Vue.set(target, key, value)
想要操作或新增原本沒有在 data
裡的資料時,需要使用 Vue.set(針對目標, 索引, 值)
強制將資料寫入 data。
1// methods 裡的 cantWork 2cantWork: function () { 3 Vue.set(this.arrayData, 0, { 4 name: '阿強', 5 age: 99 6 }); 7 console.log(this.arrayData); 8} 9
純數字的迴圈
除了使用陣列或物件,也可以使用純數字的迴圈。
1<ul> 2 <li v-for="item in 10">{{ item }}</li> 3</ul> 4
使用 v-for="item in 一個數值"
,數值是多少,迴圈就會跑幾次。
在 Template 上使用 v-for
如果需要同時使用 v-for
與 v-if
的話,可以藉由在 <template>
標籤上使用 v-for
,唯一值 key
綁定在內部元素上的方式。
注意!雖然在官方文件的範例 v-for on a template 當中並沒有綁定 key
,但我認為還是應該加上 key
,目的是讓 Vue 在演算上能夠區分出元素的唯一性,因此我一樣會做綁定 key
的動作。
1<ul> 2 <template v-for="item in items"> 3 <li :key="item.uid" v-if="true">{{ item.msg }}</li> 4 <li class="divider" role="presentation"></li> 5 </template> 6</ul> 7
以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫