0%

Vue.js List Rendering 列表渲染

如果要把一個陣列或物件渲染到畫面,在原生的 JS 我們可以用迴圈或 forEach 以遍歷的方式將陣列的資料顯示,如果用 ES6 就可用 for…of 循環語句。
在 Vue 裡要遍歷陣列的方法並不難,只是遍歷陣列和物件的方式稍有不同。
去 codepen 看看效果

以 v-for 遍歷陣列顯示

陣列列表顯示的方法是使用v-for指令,在遍歷的時候語法為<li v-for="(p, index) in persons" :key="index"></li>
在使用v-for時要記得加上:key 讓單筆的屬性有唯一值,這個陣列的唯一值是 index。
在上面的語法範例,可以想成是<li v-for="(單個陣列, index索引值) in 陣列" :key="index唯一索引值"></li>

假設我們有個陣列:

1
2
3
4
5
6
7
8
9
10
11
12
persons: [{
name: 'Ayda',
age: 18
},
{
name: 'Tracy',
age: 24
},
{
name: 'Philippe',
age: 42
}

在 HTML 我們可以這樣寫,就可以在頁面渲染出陣列的列表:

1
2
3
4
5
<ul>
<li v-for="(p, index) in persons" :key="index">
{{ index }} --- {{p.name}} --- {{p.age}}
</li>
</ul>

以 v-for 遍歷物件顯示

遍歷物件的方法也差不多,只是物件並沒有索引值,所以唯一值就會抓取 key 值,如:
v-for="(value, key) in persons[1]" :key="key"
可以想成:
v-for="(value屬性值, key屬性鍵值) in persons物件[1]" :key="key唯一鍵值"
每一個 key 值都需不相同。另外,遍歷物件的功能並不常用。

1
2
3
4
5
6
<ul>
<!-- 提取單筆 -->
<!-- <li v-for="(value, key) in persons[1]" :key="key">{{value}} -- {{key}}</li> -->
<!-- 提取全部 -->
<li v-for="(value, key) in persons" :key="key">{{value}} -- {{key}}</li>
</ul>

是改變了陣列本身還是陣列內部的資料?

在 Vue 裡要做到刪除、更新、增加陣列並須先了解 Vue 的運作,要先分清楚我們所操作的是否有改變到陣列本身?還是更改到陣列內部的物件。
例如,如果我們使用this.persons = []我們把空陣列指向 persons物件,陣列因此成為空陣列,這樣的動作是有更動到陣列「本身」。
但是如果只是去改變陣列內物件的屬性、值,這就只有更動到陣列內部結構。這樣的內部結構改變 Vue 無法知道。
Vue 只會監視 persons 這個陣列的改變,而不會監視陣列內部資料的改變。

1
2
let obj = {}; // 改變物件本身
obj.t = 1; // 只改變了物件的內部結構資料

變異方法對原生陣列方法進行包裹

解決的方法是使用 Vue 的「變異方法」 (mutation method)。

在 Vue 的官網上,列表渲染裡的「陣列更新檢測」有寫到,Vue 會將被偵聽的陣列的變異方法進行包裹,然後才將會觸發頁面的部分更新。

陣列裡有這些函式可改變陣列的內部結構,在 Vue 裡用這些方法時,如增加、刪除,用這些方法已不是 JS 的原生方法,而是 Vue 有特殊處理包裹過,包裹的過程會經過兩個步驟:呼叫原生方法函式與更新頁面,也就是 Vue 重寫了一遍這些方法,讓這些方法可以檢測到陣列內部資料的變化。如果 Vue 沒做這些包裹處理,那麼 Vue 就無法檢測到陣列內部資料的變化。

在做陣列內部資料的更動更新,一定要使用以下這些方法,才能讓陣列內部資料變化,自動更新到頁面上。

這些被 Vue 重新包裹過的方法成為「變異方法」有:push()pop()shift()unshift()splice()sort()reverse()

其中,splice() 的功能很強大,可以一次辦到增加、刪除、修改。

刪除、更新、增加的寫法

以範例來說,我們先在頁面增加三個分別為刪除、更新、增加的按鈕,這個範例只是簡單的介紹其運作的方法。

1
2
3
4
5
6
7
8
<ul>
<li v-for="(p, index) in persons" :key="index">
{{ index }} --- {{p.name}} --- {{p.age}} --<button @click="deleteP(index)">
Delete
</button>
-- <button @click="updateP(index, {name:'Fanny', age: 25})">Update</button>
</li>
</ul>

再來我們來看在 Vue 裡的刪除、更新、增加這三個方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const vm = new Vue({
methods: {
deleteP(index) {
this.persons.splice(index, 1)
},
updateP(index, newP) {
// this.persons[index] = newP
// 這樣的做法因為無原生陣列函式,所以在vue 不會起作用,也不會自動更新頁面
// console.log(this.persons[index], newP)
this.persons.splice(index, 1, newP)
},
addP(newP) {
this.persons.push(newP)
}
}
)}

如果熟悉上面的操作,應該就可以試著寫出一個簡單的 todoList 了。
接下來就要來介紹排序的部分囉!

參考:
列表渲染 — Vue.js
ES6-遍曆數組 JavaScript
ES5 和 ES6 數組遍歷方法詳解