[Vue] 跟著 Vue 闖蕩前端世界 - 13 使用 keep-alive 保留表單狀態

  • 3590
  • 0
  • Vue
  • 2018-08-31

在填寫多步驟式的表單資料時,若需要在回上一步後顯示先前填寫過的資料,可以使用 keep-alive 標籤包裹,讓指定的步驟組件狀態被快取,輕鬆完成這類需求。

前言


故事的開端在於筆者依據需求完成了一個多步驟式的表單填寫功能,而當時需求只有單方向的填寫,並無返回上一步的功能;正當大夥都興高采烈的準備收工時,客戶突然覺得應該要有「上一步」才比較人性化!

這時腦中瞬間浮現了許多實作的思路 (就是資料傳來傳去 or 存放在 Vuex 中來保留狀態),總之就是麻煩事一件。好在下個瞬間我就突然想起之前在爬官方文件有瞄到什麼 keep 啥的東西,似乎就是我需要的東西,因此本文簡單介紹一下 keep-alive 的使用情境囉。

 

 

keep-alive 簡介


Vue 本身內建 keep-alive 組件用於快取包在這個組件內的組件資料及狀態,使原本需要被摧毀 (destroy) 的組件,避免被摧毀且保持原有的狀態,因此若需保留組件狀態可以用 keep-alive 標籤包裹起來即可;當然我們也可以指定那些組件才需要被快取,keep-alive 提供了兩個 prop 供開發者使用:

  • include:  標記「需要」被快取的組件名稱 (其餘都不快取)
  • exclude: 標記「不需」被快取的組件名稱 (其餘全部快取)

    以上兩種參數都可以擺放 String, RegExp 或 Array 型態資料

 

以下範例示範三種傳入 include 屬性的資料格式,皆表示當動態組件 view 名稱為 a 或 b 的時候,該組件會被快取起來(不被摧毀);當 view 改為其他動態組件後再切回 a 或 b 組件時,先前填寫的資料會依舊存在畫面上。

<!-- comma-delimited string -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- regex (use `v-bind`) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- Array (use `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>
範例中使用的是動態組件的使用情境,如果不熟悉可以參考一下官方說明
由於被快取的組件已經不會被摧毀,因此重新顯示的時候並不會觸發 mounted 事件,我們可以透過 activated 與 deactivated  兩個新事件作為組件顯示及離開的觸發時機。

 

 

單向填寫表單 - 無保存資料


在實作這種步驟式表單,筆者習慣會在單個 page 組件中擺放各步驟表單組件,然後透過 step 來切換顯示需呈現的畫面;這樣的好處就是當用戶無論在哪個步驟中,只要按下瀏覽器左上角的上一頁鍵,會回到進入表單的入口頁,不會有機會透過瀏覽器上下頁來「隨意地」在各步驟中遊走,最多僅能依照頁面上提供的功能按鍵來順著規畫邏輯切換填寫步驟。

 

無提供「上一步」功能的頁面組件代碼約略如下,透過 step 來切換顯示需呈現的表單組件。

<template>
  <div>

    <!-- 挑選旅遊國家 -->
    <step1-tour v-if="step===1" @done="goNext" />

    <!-- 填寫遊客資料 -->
    <step2-passenger v-if="step===2" @done="goNext"/>

    <!-- 確認資料無誤 -->
    <step3-confirm v-if="step===3" @done="goNext" />

  </div>
</template>

<script>
import step1Tour from './components/step1Tour'
import step2Passenger from './components/step2Passenger'
import step3Confirm from './components/step3Confirm'

export default {
  name: 'BookTour',
  data () {
    return {
      step: 1
    }
  },
  methods: {
    goNext: function () {
      this.step += 1
    }
  },
  components: {
    step1Tour,
    step2Passenger,
    step3Confirm
  }
}
</script>
當 step 切換後,在 v-if 條件不成立的組件就會被摧毀,也就表示裡面的資料已經消失。

 

 

套用 keep-alive 保存資料


一般表單填寫的邏輯通常會保留前步驟填寫過的資料,且在返回後再進入下個步驟時,清空表單並依照前步驟輸入的資料初始新步驟選單資料,所以簡單歸納以下兩個需求。

  1. 保留當前步驟「前」的所有填寫資料 
  2. 移除當前步驟「後」的所有填寫資料

 

要如何有效率的控制須保存的步驟資料,最好的方法就是一切都是全自動,可以透過 step 的變化來自動定出須保存的表單組件範圍,因此首先需要先訂出 flowSteps 來決定各步驟所對應的表單組件清單;接著定義 aliveInclude 計算屬性,可隨著 step 變化來動態計算當下需要保留狀態的表單組件清單。最後將這個清單導入 keep-alive 的 include 屬性,告知當前步驟需保存的表單組件範圍,而其他不須保存的資料也會一併清除。

實作的示意步驟如下:

  1. 加入回上一步的事件 (可切回上個 step 位置 )
  2. 定義步驟編號及對應的表單組件名稱 (flowSteps)
  3. 依據當前步驟 step 篩選出需保存表單組件清單 (aliveInclude)
  4. 加入 keep-alive 並指定 aliveInclude 來保存目前 step 之前的所有表單組件

 

最後來驗證一下結果是否如預期呈現。首先,只要點選上一步就會回到前一步驟並且保留原始資料;若點選繼續時,下個步驟的表單不會有殘存先前填寫過的資料。沒錯這就是我們要的效果!

妥善利用 keep-alive 特性,可以非常輕鬆寫意地完成這類需求。

 

 

參考資訊


vue doc: keep-alive

 

 


希望此篇文章可以幫助到需要的人

若內容有誤或有其他建議請不吝留言給筆者喔 !