Day15 LocalStorage

Demo

終於接觸到了LocalStorage

Window.localStorage

我們可以將資料儲存在瀏覽器中,而且資料不會因為關閉瀏覽器而消失!

  • 新增

    1
    localStorage.setItem(`myCat`, `Tom`);
  • 取得

    1
    let cat = localStorage.getItem(`myCat`);
  • 移除

    1
    localStorage.removeItem(`myCat`);
  • 清除所有

    1
    localStorage.clear();

MDN詳細介紹

回到題目:

  1. 當我們載入畫面時,網頁會到localStorage撈取資料,並將資料渲染在畫面上。
  2. 按下送出後我們會將input的值存入一個變數中,再把這個值存入localStorage,同時渲染在畫面上。
  3. 按下checkbox改變資料內容,也要同時存入localStorage。

建立變數和事件

先建立目前可能會使用到的變數

1
2
3
4
5
6
const submitBtn = document.querySelector('input[type="submit"]');//送出
const inputArea = document.querySelector('input[type="text"]');//輸入
const display = document.querySelector('.plates')//整個菜單
const items = [];//儲存資料

submitBtn.addEventListener('submit',submit)

送出/儲存資料

原本的submit預設功能我們透過e.preventDefault()將它關掉。
接著為了預防送出空資料,我們做一個簡單的判斷inputArea.value
建立一個變數myitem儲存我們的資料
再將這筆資料存入一開始建立的items陣列中

接著也就是這次的重點
透過localStorage.setItem()將資料存入localStorage

items是自訂的名稱,也就是localStorage資料庫中的key,之後透過這個名稱去選到這筆資料。後面參數是我們要存入的資料。

1
2
3
4
5
6
7
8
9
10
11
12
13
function submit(e){
e.preventDefault();
if(inputArea.value){//有輸入值才存取
let myitem = {
name: inputArea.value,
done: false
}
items.push(myitem)
localStorage.setItem('items',JSON.stringify(items))//存入localStorage
show()
}
inputArea.value=''//清空輸入欄位
}

注意:我們必須透過JSON.stringify()將資料轉換為字串再存入localStorage
沒有轉為字串的話:

又再一次看到這兩個功能了

  1. JSON.stringify():將資料轉為 JSON 格式的字串。
  2. JSON.parse(myJSON):將資料由 JSON 格式字串轉回原本的資料內容及型別。

正確顯示:

渲染到畫面上

資料確認存入localStorage無誤後,我們就要讓資料渲染到畫面上
注意:此時我們的item還是空陣列,我們先做一筆假資料測試,下一步會將localStorage資料同步到item中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const items = [{
name: '假資料',
done: false
}];

function show(){//將資料透過map轉化為字串並消除逗號
display.innerHTML = items.map((item,key)=>{
return `
<li>
<input type="checkbox" data-index=${key} id="item${key}" ${item.done ? 'checked' : ''} >
<label for="item${key}">${item.name}</label>
</li>
`
}).join('')
}
show()

我們透過map將每一筆資料轉換成字串放入innerHTML中,而我們在Day6也有做過類似的事情,最後要加入.join('')將陣列轉出來的逗號刪除。
最後自己呼叫show()一次,因為網頁一載入就需要渲染第一次。

將資料同步到變數中

我們的變數items = []必須存取localStorage的資料(如果有資料的話)
所以我們可以這麼做,這邊使用到的是.getItem()

1
2
3
4
5
6
let items = [];
function load(){
if(!localStorage.getItem('items')) return //如果localstorage沒有值就return
items = [...JSON.parse(localStorage.getItem('items'))]
}
load()

因為我們取得的是JSON格式的字串,所以必須透過JSON.parse()將字串轉回原本的資料內容及型別。

畫面一載入我們就去撈資料,並且將資料透過展開運算子(Spread Operator)塞入items

展開運算子(Spread Operator)真的很酷,我們在Day14使用過

精簡版:直接定義items為去取得資料空陣列

1
const items = JSON.parse(localStorage.getItem('items')) || [];

Checkbox改變資料

我們的checkbox是動態產生的DOM結構,所以無法在一開始就透過定義變數去取得

寫法一:將事件觸發設定在父層.plates
寫法二:將事件觸發寫在show()函式內。此時已可選到input,但程式碼比較醜。

寫法一:

1
2
3
4
5
6
7
8
9
10
11
const display = document.querySelector('.plates')

function checkHandler(e){
if (!e.target.matches('input')) return;
let target = e.target
let targetIndex = target.dataset.index
items[targetIndex].done = !items[targetIndex].done
localStorage.setItem('items',JSON.stringify(items))//存入localStorage
}

display.addEventListener('click',checkHandler)

關鍵:因為觸發在.plates所以e.target不一定是input,不是點到input就做阻擋

寫法二:

1
2
3
4
5
6
7
8
9
function show(){
//..
//...
const checkboxes = document.querySelectorAll('input[type="checkbox"]')
checkboxes.forEach((checkbox)=>{
checlbox.addEventListener('click',checkHandler)
})
}
show()

程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
const submitBtn = document.querySelector('input[type="submit"]');
const inputArea = document.querySelector('input[type="text"]');
const display = document.querySelector('.plates')

const items = JSON.parse(localStorage.getItem('items')) || [];
// let items = [];

// function load(){
// if(!localStorage.getItem('items')) return //如果localstorage沒有值就return
// items = [...JSON.parse(localStorage.getItem('items'))]
// console.log(items)
// }
// load()

function submit(e){
e.preventDefault();
if(inputArea.value){//有輸入值才存取
let myitem = {
name: inputArea.value,
done: false
}
items.push(myitem)
localStorage.setItem('items',JSON.stringify(items))//存入localStorage
show()
}
inputArea.value=''//清空輸入欄位
}

function show(){//將資料透過map轉化為字串並消除逗號
display.innerHTML = items.map((item,key)=>{
return `
<li>
<input type="checkbox" data-index=${key} id="item${key}" ${item.done ? 'checked' : ''} >
<label for="item${key}">${item.name}</label>
</li>
`
}).join('')
}
show()

function checkHandler(e){
if (!e.target.matches('input')) return;
let target = e.target
let targetIndex = target.dataset.index
items[targetIndex].done = !items[targetIndex].done
localStorage.setItem('items',JSON.stringify(items))//一樣存入localStorage
}

submitBtn.addEventListener('click',submit)
display.addEventListener('click',checkHandler)
0%