iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 5
0
Modern Web

認真學前端開發 - 以 TodoList 為例系列 第 5

Day05 - TodoList js - II

今日主題是透過 TodoList 來學習

  • 原生 javascript 裡的 API
  • 讀 MDN 上的文件
  • 你的 this 是我的 that 還是窗戶

Todo List - codepen

第二段代碼

// Click on a close button to hide the current list item
var close = document.getElementsByClassName("close");
var i;
for (i = 0; i < close.length; i++) {
  close[i].onclick = function() {
    var div = this.parentElement;
    div.style.display = "none";
  }
}

// Add a "checked" symbol when clicking on a list item
var list = document.querySelector('ul');
list.addEventListener('click', function(ev) {
  if (ev.target.tagName === 'LI') {
    ev.target.classList.toggle('checked');
  }
}, false);
  • 昨天我們在每個節點都加上一個 <span class="close">x<span>
  • 使用 getElementsByClassName 取得符合 class 等於 close 的 HTMLCollection
  • 然後把每個 close element 都給個 onclickanonymous function
  • 如果好奇為什麼這裡的 function 出現了 this,而這個 this 居然是 close[i] 那一個 node 這邊稍作一點說明

這邊的 this

在 javascript 中 this 通常指的是呼叫該 method 的人,而非該 method的物件本身,例如當 close[0] 被點擊了,底層的十之八九是 close[0].onclick(e) 來執行這個 function 那這個 this 就會指向 close[0],所以通常給 Node event function 會利用這個特性直接使用 this 來操作該節點

如果試試看改成這樣會發生什麼事呢?

  close[i].onclick = function() {
    var div = this.parentElement;
    div.style.display = "none";
  }
  var myImmediateEvent = close[i].close;
  myImmediateEvent();

會發現 this 壞掉了,而 console 的 error 說的是 undefined 沒有 styleproperty

原因是呼叫 myImmediateEvent 沒有主人,順其自然就是最外層的呼叫 myImmediateEvent 了

而 window 上的 property 沒有 parentElement 這個 property 所以頁面就壞掉啦~

假設 window 有這個 property 其實更危險,因為可能改動到其他 module 的功能。

this 的原理可以詳讀

第三段代碼

// Create a new list item when clicking on the "Add" button
function addTodo() {
  var li = document.createElement("li");
  var inputValue = document.getElementById("todo-input").value;
  var t = document.createTextNode(inputValue);
  li.appendChild(t);
  if (inputValue === '') {
    alert("請輸入待辦事項");
  } else {
    document.getElementById("todo-list").appendChild(li);
  }
  document.getElementById("todo-input").value = "";

  var span = document.createElement("SPAN");
  var txt = document.createTextNode("x");
  span.className = "close";
  span.appendChild(txt);
  li.appendChild(span);

  for (i = 0; i < close.length; i++) {
    close[i].onclick = function() {
      var div = this.parentElement;
      div.style.display = "none";
    }
  }
}

最後是這一段 addTodo function 的代碼
這邊的流程就是

  1. 創建一個 <li></li> 的 element然後加到 div#todo-list 後面
  2. 再創立一個 <span>x</span> 加到 #1 創建的 li 之後
  3. 最後是把 close 這個 HTMLCollection 的參數設定 onclick method

如果有看昨天的說明就會了解 live 的 HTMLCollection 原理,所以這個 addTodo function 才能這樣子跑

createTextNode vs innerHTML

有沒有覺得很奇怪,第一段代碼的地方 <span>x</span> 這個節點是用 span.innerHTML="x" 加上去的,但這段代碼的 span 上的 xli 的文字是用 createTextNode

我覺得這段 javascript 很容易踩到雷,所以要小心

同樣先看 MDN 好像沒有特別講
不過意思是說你輸入的文字都會幫你加到節點裡
而 innerHTML 會把輸入的文字變成 HTML ,然後就有可能被使用者用文字攻擊囉~

試試這段代碼

var child = document.createElement('div')
child.innerHTML = '<div></div>'
console.log(child)

所以記得要小心使用 innerHTML

到目前為只有看到三種 click event 的寫法,想必大家也很好奇其中的奧妙,明天來看看 event 的部分吧!


上一篇
Day04 - 用 js 存取 DOM
下一篇
Day06 事件處理
系列文
認真學前端開發 - 以 TodoList 為例30

尚未有邦友留言

立即登入留言