---
# System prepended metadata

title: '2019/10/21 VueJS 教學筆記: 緩存機制'
tags: [LocalStorange, Cookies, VueJS]

---

---
title: '2019/10/21 VueJS 教學筆記: 緩存機制'
disqus: hackmd
---

10/21 VueJS 教學筆記: 緩存機制
===

綱要

[TOC]

學習如何使用暫存，並比較三種方式之間的不同
---

==**Cookies**==

可設置失效時間，未指定時間則是關閉瀏覽器就失效，儲存容量約 4 KB。
與其他兩種方式不同，缺點是會夾帶在HTTP中，當保存了過多的資料時會影響效能。

==**Local Storange**==

永久保存，除非進行清除，有 5 MB 左右的儲存容量。
不參與 Server 溝通，僅保存在瀏覽器中。

==**Session Storange**==

關閉頁面或瀏覽器後會自動進行清除，同樣有 5 MB 左右的儲存容量、其它特性與 Local Storange 相同。

練習：LocalStorange 的例子
---

[Codepen範例](https://codepen.io/fortes-huang/pen/MWWbdxz)

**Context:**

1. 避免填寫到一半的表單因為斷線、重新整理、或誤關閉網頁造成必須從頭開始填寫狀況
2. 為了方便再次進入填寫步驟時可以自動帶入User上一次的填寫內容，需要載入已儲存的欄位內容

**Force:**

1. 使用Local Storange將輸入一半的表單內容保留，重新整理時務必顯示已填寫的部分內容
2. 當按下「載入上一次填寫的內容」時，完整的自動填寫上一次「成功送出」後的所有欄位

題解
---
[Github範例](https://github.com/fortes1219/vue_0803/blob/0803/src/components/home/LocalStorange.vue)

`data()`中定義表單綁定的 v-model
```javascript=
data() {
  return {
    form: {
      name: '',
      prefer: '',
      date: '',
      time: '',
      type: []
    },
    savedForm: {},
    preferItems: [
      { id: 0, name: 'Ruler' },
      { id: 1, name: 'Saber' },
      { id: 2, name: 'Archer' },
      { id: 3, name: 'Lancer' },
      { id: 4, name: 'Rider' },
      { id: 5, name: 'Caster' },
      { id: 6, name: 'Assassin' },
      { id: 6, name: 'Berserker' },
      { id: 8, name: 'Avenger' },
      { id: 9, name: 'Alterego' },
      { id: 10, name: 'Foreigner' }
    ]
  }
}
```

在`methods`中增加重置表單的方法：

```javascript=
methods: {
  // 建議把這個resetForm()另外編入utils做export const共用方法
  resetForm(target) {
    let reset = (obj) => {
      Object.keys(obj).map(key => {
        if (obj[key] === Object(obj[key])) {
          reset(obj[key])
          if (obj[key] instanceof Array) {
            obj[key] = []
          }
          return
        } else {
          obj[key] = ''
        }
      })
    }
    reset(target)
  }
  
  handleReset(obj) {
    this.resetForm(obj)
    obj.date = ''
    obj.time = ''
  },
}

```



接著是`template`的部分，因為需求中有「避免填寫到一半的表單因為斷線、重新整理、或誤關閉網頁造成必須從頭開始填寫狀況」，所以透過綁定表單物件`@change` 事件，當內容變更時就寫入暫存。

```htmlmixed=
<el-form ref="form" :model="form" label-width="150px" style="width: 600px">
  <el-form-item label="御主姓名">
    <el-input v-model="form.name" @change="onChangeItem"></el-input>
  </el-form-item>
  <el-form-item label="偏好職階">
    <el-select v-model="form.prefer" placeholder="請選擇偏好職階" @change="onChangeItem">
      <el-option v-for="(item, index) in preferItems" :key="index" :label="item.name" :value="item.id"></el-option>
    </el-select>
  </el-form-item>
  <el-form-item label="申請時間">
    <el-col :span="11">
      <el-date-picker type="date" placeholder="選擇日期" v-model="form.date" style="width: 100%;" @change="onChangeItem"></el-date-picker>
    </el-col>
    <el-col :span="11">
      <el-time-picker placeholder="選擇時間" v-model="form.time" style="width: 100%;" @change="onChangeItem"></el-time-picker>
    </el-col>
  </el-form-item>
  <el-form-item label="想成為御主的理由">
    <el-checkbox-group v-model="form.type" @change="onChangeItem">
      <el-checkbox label="可以和好多女性從者這個那個" name="type"></el-checkbox>
      <el-checkbox label="拯救世界" name="type"></el-checkbox>
      <el-checkbox label="可以拿好多好多的聖晶石" name="type"></el-checkbox>
      <el-checkbox label="我是興趣使然的御主" name="type"></el-checkbox>
    </el-checkbox-group>
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="loadLastData">載入上一次填寫內容</el-button>
    <el-button type="primary" @click="onSubmit">送出申請</el-button>
    <el-button @click="handleReset(form)">重置表單</el-button>
  </el-form-item>
</el-form>
```

在`methods`增加一個事件處理`onChangeItem()`：

```javascript=
methods: {
  onChangeItem() {
    // 每次輸入input或者勾選了checkBox、變更select時，兩秒後自動寫入localStorange
    setTimeout( () => {
      // 如果不在寫入時先將物件轉JSON字串，則寫入結果只會顯示 [object object]
      localStorage.setItem('form', JSON.stringify(this.form))
    }, 2000)
  },
}

```

頁面載入時就撈回剛剛填到一半的進度：

```javascript=
methods: {
  // onChangeItem()
  //...
  
  reloadSavedForm() {
    // 使用JSON.parse()將LocalStorange中的資料轉回可利用的object
    const stored = JSON.parse(localStorage.getItem('form'))
    if (stored !== null) {
      this.form = stored
    }
  }
},

created() {
  // created階段時就進行
  this.reloadSavedForm()
}

```

最後是成功送出表單後，需要儲存已送出的內容：

```javascript=
methods: {
  // onChangeItem()
  // reloadSavedForm()
  //...
  
  // 表單送出
  onSubmit() {
    localStorage.setItem('submitSuccess', JSON.stringify(this.form))
  },
  // 載入前一次成功送出的內容
  loadLastData() {
    this.savedForm = JSON.parse(localStorage.getItem('submitSuccess'))
    this.form = this.savedForm
  }
}  
```

Cookies 的例子
---

先安裝 [js-cookie](https://github.com/js-cookie/js-cookie)

`npm install js-cookie`

定義 Cookies 設置、取得、移除三個行為：

```javascript=
import Cookies from 'js-cookie'
// ...
methods: {
  setCookies() {
    // 這裡的expires設置 1 的時候是指「一天內有效」，根據js-cookie官方文件記載，還支援new Date()的方式設置有效時間
    // 寫入時同樣要注意是否轉JSON字串的問題
    Cookies.set('cookie', JSON.stringify(this.form), { expires: 1 })
  },
  
  removeCookies() {
    Cookies.remove('cookie')
  },
  
  getCookies() {
    this.savedForm = JSON.parse(Cookies.get('cookie'))
    console.log(this.stored)
  }
}
```






###### tags: `VueJS` `LocalStorange` `Cookies`

