JavaScript 小學 — Local Storage 和data-*

Jordan Tseng
JordanTTCDesign
Published in
14 min readJan 16, 2021

local storage是什麼用在哪呢?

local storage → 本地端的資料庫,於 HTML5 新加入了一個屬性,可以暫存一些資料,比之原本的 cookie 可以更好的儲存資料。例如我們在逛網拍時,都會有剛剛瀏覽的商品,他就是暫存在你的本地端記憶體,或是像是密碼、自動登入也是一樣。🤘🤘🤘

如何找到這個 local storage資料呢?

在 Chrome 瀏覽器→檢視→選項 application 中查詢到,他是透過網址做綁定對應不同資料群,除非使用者自己清除。👷‍♂️

透過 local storage 儲存資料、讀取資料

瀏覽器中會把 localStorage 的值型別限定為 string ,我們日常比較常見的JSON物件型別,就需要轉換成 string 才能放在 local storage。而 local storage 資料是以 key : value 形式儲存。

兩個簡單的 function:儲存資料 setItem() 、讀取資料 getItem(),以下面的簡單小範例是→setItem()把 Jordan 儲存在 myName 裡:

var str ='Jordan';
localStorage.setItem('myName',str)//(key,value)

再來就是用getItem(key值)

var data = localStorage.getItem('myName')
console.log(data);//Jordan

下面做了一個小練習:透過輸入框輸入名字,再 setItem() 把值儲存到 localStorage 中,再透過 getItem() 抓到資料顯示在列表中:

//宣告
const btnSet=document.querySelector('.btnSet');
const btnCall=document.querySelector('.btnCall');
let nameList=document.querySelector('.nameList');
var myName='';
//存資料
function saveName(e){
myName=document.querySelector('.txt').value;
console.log(myName);
localStorage.setItem('myName',myName);
}
//顯示資料
function callName(e){
let nowName=localStorage.getItem('myName');
nameList.innerHTML=`<li>${nowName}</li>`
}
//監聽動作
btnSet.addEventListener('click',saveName);
btnCall.addEventListener('click',callName);

運用陣列儲存資料

如果要把上面的範例改成可以儲存多筆資料的話,就要用「陣列」儲存了,但在 localStorage 的value 要存陣列要先用 JSON.parse() 轉換成字串。讀取時就要用 JSON.stringify() 編譯,把字串轉回成陣列。

JSON.parse():把string⇒Array

JSON.stringify():把Array⇒String

下面改寫的作法基本是陣列改成字串存入之後"['jordan','jordan2']",讀取時,把字串取出改成陣列接著用 forEach 迴圈轉成<li> 也另存到另外一個字串中才用 innerHTML() 渲染畫面。

//宣告
const btnSet=document.querySelector('.btnSet');
const btnCall=document.querySelector('.btnCall');
let nameList=document.querySelector('.nameList');
//改成[];
var myName = [];
//存資料
function saveName(e){
let str = document.querySelector('.txt').value;
myName.push(str);
let myNameString= JSON.stringify(myName);
localStorage.setItem('myName',myNameString);
call();
}
//顯示資料
function callName(e){
let nowName=localStorage.getItem('myName');
//改成
let nowNameArray=JSON.parse(nowName);
let nowNameList='';
nowNameArray.forEach(function(item){
nowNameList+=`<li>${item}</li>`
})
nameList.innerHTML = nowNameList;
}
//監聽動作
btnSet.addEventListener('click',saveName);
btnCall.addEventListener('click',callName);

陣列裡面有物件同樣可以用這種方式儲存的喔~

var country=[{farmer='Jordan'}];
//轉換
var countryString=JSON.stringify(country);
console.log(countryString);//'[{farmer='Jordan'}]'
localStorage.setItem('countryItem',countryString);
var getData=localStorage.getItem('countryItem');
var detDataArray=JSON.parse(getData);

搭配 HTML 自訂屬性 data-* 透過 dataSet 讀取自訂資料

允許在讀取與寫入模式時使用 HTML 或 DOM 的標籤中放自訂屬性,為什麼要自訂屬性呢🧐🤨?因為可以使用JS去做互動🤩🤩,只要用 data- 開頭的來當作屬性名稱就可以放入對應資料,而 data- 後面就是接自訂的類別名稱。

<p class="me" data-num="0" data-lastName="Tseng" data-dog="poddle" >Jordan</p>

只要對該目標.dataset.名稱就可以取出,如下面:

console.log(document.querySelector('.me').dataset.num);//0
console.log(document.querySelector('.me').dataset.lastName);//Tseng
console.log(document.querySelector('.me').dataset.dog);//poddle

另一個範例是透過自訂屬性抓到名稱,再搭配網址就可以做成不同網址唷🙆‍♂️

<h2>以下有兩顆按鈕,是部落格推薦連結,請抓取 data-id 的值後可以進行轉址</h2>
<ul>
<li>點擊 Tom 時,網址為 <https://www.hexschool.com/?recommend=tom></li>
<li>點擊 John 時,網址為 <https://www.hexschool.com/?recommend=John></li>
</ul>
<button class="btn-tom" data-id="tom">Tom 推薦六角學院</button>
<button class="btn-john" data-id="John">John 推薦六角學院</button>

以上面的例子是.dataset.id ,搭配 location.href 轉址:

const changeTom = document.querySelector('.btn-tom');
const changeJohn = document.querySelector('.btn-john');
//讀取
let tomId = changeTom.dataset.id;
let johnId = changeJohn.dataset.id;
//附加網址
function recommendJohn(){
location.href = `https://www.hexschool.com/?recommend=${johnId}`;
}
function recommendTom(){
location.href = `https://www.hexschool.com/?recommend=${tomId}`;
}
//監聽事件
changeJohn.addEventListener('click',recommendJohn,false);
changeTom.addEventListener('click',recommendTom,false);
console出的結果

dataset搭配陣列的運用

用 dataset 把陣列渲染出來,在後續也能對陣列中每一筆資料做操作。

我們來做一個練習,第一步先在畫面中渲染出陣列資料:

var school = [{teacher:'Jordan'},{teacher:'Zoe'}]
var list = document.querySelector('.list');
//顯示老師資料
function readerList(){
let str = '';
let len = school.length;
for(let i = 0;len>i;i++){
str+='<li data-num="'+i+'">'+school[i].teacher+'</li>'
}
list.innerHTML = str;
}
readerList();

渲染成功後,點擊老師名字就可以,產生 js 效果。

注意在效能上,要對一個 li 綁定是很耗費效能😱,所以要綁定在 ul 上面😋😋,再透過檢查點擊目標的 nodeName 是否為 li,不是 lireturn 跳出 function

//點擊讀取畫面老師列表資料
function getListData(e){
var num = e.target.dataset.num;
console.log(e.target.nodeName);
if(e.target.nodeName !== 'LI'){return};
alert('你選擇的老師是'+school[num].teacher)
}
//綁定list來監聽
list.addEventListener('click',getListData,false);

dataset 搭配 splice 刪除陣列運用

再來就是要發揮data的強大效用了,大家都用過今日代辦事項的軟體,利用陣列操作 push,splice 兩種方法和最前面的localStorage功能,就可以做出簡易的代辦事項軟體唷👍~

先解釋:splice() 中有兩個要填,第一個是第幾個開始刪除,第二個值是刪除幾個,會寫成:

list.splice(num,1);
//這裡的num就會對應data-number中的值

👉開始吧!!第一步:先在html中新增一個輸入框、按鈕以及ul:

<input type="text" class="textClass">
<input type="button" class="btnClass" value="點擊">
<ul class="todoList"></ul>

👉第二步:取的dom元素,這裡要注意的是todoList可能不會有資料所以用了 ||[] ,就是當沒資料時會帶入一個空陣列。

const btnSave= document.querySelector('.btnClass');
var todoList= document.querySelector('.todoList');
var todoListData=JSON.parse(localStorage.getItem('todo'))||[] ;

👉第三步:首先想到應該是製作 input 陣列的 function 吧~

function inputList(e){
let inputContent= document.querySelector('.textClass').value;
let todo={content:inputContent};
//把新資料塞入陣列當中
todoListData.push(todo);
//這裡會放一個接下來寫的更新function,當有輸入新資料就會更新一次
update();
//最後記得清空輸入框
document.querySelector('.textClass').value='';
}

👉第四步:更新 local Storage 的資料。

function update(e){
//前面有說要先轉成文字才塞入本地庫中
let todoListString=JSON.stringify(todoListData);
localStorage.setItem("todo", todoListString);
//塞入成功就渲染畫面更新畫面資料
render();
}

👉第五步:終於來寫渲染畫面的function,把 todoListData 中每一筆資料弄成 li ,並放入具備 data-number 的按鈕 。

//渲染function
function render(e){
let str='';
todoListData.forEach(function(item,index){
str+=`<li class="listLi">${item.content}<button data-number="${index}" class="deleteBtn btn btn-outline-secondary">刪除</button></li>`
})
todoList.innerHTML= str;}
}

👉最後步驟:寫一個 delete function 用來對號碼刪除對應數字的資料,記得這裡也是利用綁定ul再用includes()查詢看class是否包含.deleteBtn

function deleteList(e){
let targetClassName=e.target.className;
if(targetClassName.includes('deleteBtn')){
e.preventDefault();
console.log('delete OK!');
let num=e.target.dataset.number;
todoListData.splice(num,1);
update();
}
}
//監聽
btnSave.addEventListener('click',inputList,false);
todoList.addEventListener('click',deleteList,false);

用codepen,看看實際效果吧!!

--

--