點燈坊

失くすものさえない今が強くなるチャンスよ

如何對 Local Storage 處理 Boolean ?

Sam Xiao's Avatar 2020-08-27

實務上常需要儲存 Boolean 到 Local Storage,但可惜 Local Storage 只能儲存 String,因此 truefalse 會儲存成 'true''false',該如何優雅處理呢 ?

Vue 2

parse000

按下 Write true to Local Storage 會將 Boolean true 寫入 local storage。

按下 Read true from Local Storage 會將 String 'true' 讀出 local storage。

<template>
  <div>
    <button @click="onWrite">Write true to Local Storage</button>
    <button @click="onRead">Read true from Local Storage</button>
    {{ result }}
  </div>
</template>

<script>
import { pipe, either, always } from 'ramda'
import { create, env } from 'sanctuary'
import { writeStorage, readStorage, parse } from 'wink-fp'

let { fromMaybe } = create ({ checkTypes: false, env })

let onWrite = function() {
  pipe(
    always(true),
    writeStorage('isOdd')
  )()
}

let onRead = function() {
  let logOdd = () => this.result = 'Result is odd'
  let logEven = () => this.result = 'Result is even'

  pipe(
    always('isOdd'),
    readStorage,
    fromMaybe(true),
    parse,
    either(logOdd, logEven)
  )()
}

export default {
  name: 'App',
  data: () => ({
    result: ''
  }),
  methods: {
    onRead,
    onWrite
  }
}
</script>

16 行

let onWrite = function() {
  pipe(
    always(true),
    writeStorage('isOdd')
  )()
}

onWrite() 寫入 local storage。

  • 使用 always() 回傳 true
  • 使用 writeStorage()isOdd 入 local storage

23 行

let onRead = function() {
  let logOdd = () => this.result = 'Result is odd'
  let logEven = () => this.result = 'Result is even'

  pipe(
    always('isOdd'),
    readStorage,
    fromMaybe(true),
    parse,
    either(logOdd, logEven)
  )()
}

onRead() 讀出 local storage。

  • 使用 always() 回傳 isOdd
  • 使用 readStorage() 讀出 local storage
  • 由於 readStorage() 回傳 Maybe Monad,使用 fromMaybe() 讀出 Maybe 內部值,若為 Nothing 則為 true
  • readStorage() 回傳型別為 Maybe String,而 fromMaybe() 回傳為 String,需使用 parse() 將 String 'true' 轉成 Boolean true
  • 使用 either() 判斷 truefalse,若為 truthy value 則執行 logOdd(),若為 falsy value 則執行 logEven()

Vue 3

<template>
  <button @click="onWrite">Write true to Local Storage</button>
  <button @click="onRead">Read true from Local Storage</button>
  {{ result }}
</template>

<script>
import { ref } from 'vue'
import { effect } from 'vue3-fp'
import { pipe, either, always } from 'ramda'
import { create, env } from 'sanctuary'
import { writeStorage, readStorage, parse } from 'wink-fp'

let { fromMaybe } = create({ checkTypes: false, env })

let result = ref('')

let onWrite = pipe(
  always(true),
  writeStorage('isOdd')
)

let logOdd = pipe(
  always('Result is odd'),
  effect(result)
)

let logEven = pipe(
  always('Result is even'),
  effect(result)
)

let onRead = pipe(
  always('isOdd'),
  readStorage,
  fromMaybe(true),
  parse,
  either(logOdd, logEven)
)

let setup = pipe(
  always({ result, onWrite, onRead })
)

export default {
  name: 'App',
  setup
}
</script>

18 行

let onWrite = pipe(
  always(true),
  writeStorage('isOdd')
)

Vue 3 直接組合 always()writeStorage()onWrite() method 即可。

33 行

let onRead = pipe(
  always('isOdd'),
  readStorage,
  fromMaybe(true),
  parse,
  either(logOdd, logEven)
)

Vue 3 直接組合眾多 function 給 onRead() method 即可。

Conclusion

  • 雖然 local storage 儲存為 String 'true',但可透過 parse() 轉成 Boolean true,其底層就是 JSON.parse()
  • Vue 2 與 Vue 3 其實原理相同,但 Composition API 加持下明顯精簡很多,只要組合 function 即可