iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 10
0
Modern Web

Déjà-vu ? 要 Vue 過才知道系列 第 10

v- 指令 v-for 列表渲染與操控

把流程簡單化的好處很多,但風險是會忘記複雜的事情怎麼做。

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

以 v-for 遍歷陣列的渲染

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

在寫v-for時為了辨識,最好以單、複數來分別,在很多筆的資料裡(persons)中,每次拿一筆資料(person),而成為person in persons

假設我們有個陣列(其實就是 JSON 格式):

persons: [
  {
    name: 'Ayda',
    age: 18,
  },
  {
    name: 'Tracy',
    age: 24,
  },
  {
    name: 'Kira',
    age: 42,
  },
];

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

<ul>
  <li v-for="(person, index) in persons" :key="index">
    {{ index }} --- {{person.name}} --- {{person.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 值都需不相同。另外,遍歷物件的功能並不常用。

<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 這個陣列的改變,而不會監視陣列內部資料的改變。

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() 的功能很強大,可以一次辦到增加、刪除、修改。

刪除、更新、增加的寫法

以範例來說,我們先在頁面增加三個分別為刪除、更新、增加的按鈕,(如何綁定元素明天再來說~)這個範例只是簡單的介紹其運作的方法。

<ul>
  <li v-for="(person, index) in persons" :key="index">
    {{ index }} --- {{person.name}} --- {{person.age}} --<button
      @click="deletePerson(index)"
    >
      Delete
    </button>
    --
    <button @click="updatePerson(index, {name:'Fanny', age: 25})">
      Update
    </button>
  </li>
</ul>

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

const vm = new Vue({
methods: {
        // 刪除
        deletePerson(index) {
          this.persons.splice(index, 1)
        },
        // 更新
        updatePerson(index, newPerson) {
          // this.persons[index] = newP
          // 這樣的做法因為無原生陣列函式,所以在Vue 不會起作用,也不會自動更新頁面
          // console.log(this.persons[index], newP)
          this.persons.splice(index, 1, newPerson)
        },
        // 增加
        addPerson(newPerson) {
          this.persons.push(newPerson)
        }
      }
)}

如果熟悉上面的操作,應該就可以試著寫出一個簡單的 todoList 了。

每日一句法文有益身心:Merde ! --> 妹.喝.的! -->原意是拉屎的意思!跟英文的 Shit 一樣。

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


上一篇
Vue.js 實作簡易圖片瀏覽
下一篇
Vue 表單元素資料的雙向綁定 v-model
系列文
Déjà-vu ? 要 Vue 過才知道30

尚未有邦友留言

立即登入留言