練習 TodoList 的原因 TodoList 看似簡單的介面,但其實隱藏了很多小細節,記錄一下這次的練習,預計要完成的畫面如下:
 
練習重點 
切版的熟悉度。 
綁定 DOM 元素。 
紀錄資料再 localStorage。 
透過 setItem 與 getItem 實現新增待辦。 
透過 dataset 與 splice 屬性抓出排序與刪除資料。 
 
製作 TodoList 
navbar 用 Bootstrap 4 套件很快速就可以完成了,相關的 CSS 再看 codepen,就不做太多陳述。
 
下方的 content 分成兩欄,這邊稍微紀錄一下:
左邊 siderbar 設定為 Width:30%
右邊 inputbar 為 width: 67%,再往左邊推 margin-left: 3%,總共為 70%。
因為最下面的 taskList 清單想要再 inputbar 下方,且限制其寬度, CSS 設定為 width: 70% 跟 margin-left: 26%。
HTML 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <div  class ="content" >       <div  class ="siderbar" >          <ul >            <li > <a  href ="#" > 今天</a > </li >            <li > <a  href ="#" > 明天</a > </li >            <li > <a  href ="#" > 未來七天</a > </li >          </ul >        </div >        <div  class ="inputbar" >          <input  type ="text"  name ="task"  id ="task"  placeholder ="請輸入待辦事項" >          <button  class ="btn" > <i  class ="fas fa-plus" > </i > </button >        </div >             </div >      <ul  class ="taskList" >      </ul >    </div >  
 
SCSS 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 .content  {  margin-top : 3% ;   display : flex;   .siderbar {     width : 30%;     line-height : 2;     margin-right : 0;     a  {       text-decoration : none;       color : $primary-color;       &:hover {         font-weight : bold ;       }     }   }   .inputbar  {     display : flex;     margin-left : 3% ;     width : 100% ;     height : 42px ;     //限制高度,就能讓 inputbar 的高度固定,不會受 flex 影響     input  {       width : 100% ;       margin-right : 0.3em ;     }   }   .btn  {     background-color : $primary-color;     padding : 5px ;     color : #fff ;     font-size : 16px ;     width : 42px ;     &:hover {       background-color: (darken($color: $primary-color, $amount: 20%));       color : #fff ;     }   } } 
 
以上是靜態頁面 會呈現的樣子,但 todolist 需要有互動,可增加與刪除事項的功能,所以要加入 JavaScript。
JavaScript 先綁定資料,
1 2 3 4 5 6 var  btn = document .querySelector(".btn" );var  input = document .querySelector("#task" );var  list = document .querySelector(".taskList" );
 
宣告 getData 變數作為從 localStorage 取出 value,typeof 會是 string,
1 var  getData = localStorage.getItem("task" );
 
先宣告一個 getDataAry = 空值,如果 getData 是 true,會去解析 getDataAry 字串資料成陣列,否則就會空陣列。
1 2 3 4 5 6 7 var  getDataAry = "" ;if  (getData) {  getDataAry = JSON .parse(getData);  } else  {   getDataAry = []; } var  taskList = getDataAry; 
 
更新清單,組完字串後,會放在 .taskList 的 ul 中,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 updateList();  function  updateList ( )  {  var  len = taskList.length;    var  str = "" ;    for  (var  i = 0 ; i < len; i++) {     str += `          <li>           <a data-num=${i} >             <i class='fas fa-times-circle'></i>           </a>${taskList[i]}          </li>` ;       }   list.innerHTML = str;    var  taskListStr = JSON .stringify(taskList);    localStorage.setItem("task" , taskListStr);  } 
 
建立新增資料 與刪除資料 監聽事件,
1 2 3 4 btn.addEventListener("click" , getInput, false ); list.addEventListener("click" , delTask, false ); 
 
當使用者輸入資料,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function  getInput ( )  {  console .log(input.value);   var  text = input.value;    if  (text === "" ) {          alert("您未輸入事項" );      return ;   }      taskList.push(text);    input.value = "" ;    updateList();    } 
 
當使用者刪除資料,點擊到的 nodeName 為 A 或是 I 就中斷,造成點選A和 I 就結束動作,而點到後面文字,也就是 LI 則被刪除,所以要把刪除的動作放在 if 判斷內就能點 icon 圖示刪除 todo
1 2 3 4 5 6 7 8 9 10 function  delTask (e )  {  var  current = e.target.nodeName;    if  (current == "A"  || current == "I" ) {     var  currentNum = e.target.dataset.num;      taskList.splice(currentNum, 1 );    } else  {     return ;   }   updateList();  } 
 
結語 JS 的互動行為有點細,跟人腦思維不太一樣,要一個口令一個動作,也不用想得太難,要直觀一點,可能人腦的思維可以很快速的整合一件事情的內容,但 JS 是要透過很多的行為告訴電腦該怎麼完成這些很細的動作。很有趣的練習!!
附上 codepen,可以玩玩看: https://codepen.io/hnzxewqw/pen/eYmRgoJ