菜鳥筆記:簡易的 Todo-list

GlennJong
GlennJong
Jul 22, 2017 · 9 min read

https://glennjong.github.io/noob.todolist/

回歸原生 Javascript,用物件導向的概念來寫 Todo-list 功能。

快速介紹物件導向

舉一個簡單的例子

function Person(first, last) {
this.first = first;
this.last = last;
this.say = function(){
return 'I am ' + this.first + ' ' + this.last + '.'
};
}
var p = new Person('Peter', 'Parker')> p
< Person {first: 'Peter', last: 'Parker', say: function}
> p.say()
< "I am Peter Parker."

這個例子中,有個叫做 Person 的函式,以名字當作引數(arguments)設定成這個 Person 的屬性。
接著來設定一個變數 p,把 Peter、Parker 當作引數給了 Person 這個函式,用 new 建構出一個 Person 物件(object)。
所以輸入 p 時,他回傳了 Person {first: ‘Peter’, last: ‘Parker’, say: function} 物件,也就是創造出 Person 的實例。
而物件的屬性當然也可以設定成函式,就像賦予這個 Person 一個動作一樣,所以輸入 p.say() 時,則會回傳 ‘I am Peter Parker.’

透過這種方式產生出 Javascript 物件,可以確保產生的物件格式相同,並且可以快速產生,也較容易理解。
如此以來就能夠快速的建立物件,像這樣:
var b = new Person(‘Bruce’, ‘Wayne’)
var c = new Person(‘Clark’, ‘Kent’)

更詳細的物件導向請看:
https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript


應用在 Todo-list

程式拆解

Todo-list 的步驟可以理解成:
1. 建構出統一的 TodoItem 物件
2. 將取得的資訊放到 TodoItem 的屬性
3. 把這個 TodoItem 的前台物件印在 HTML 上

所以可以先把程式拆解成這樣:

function TodoList() {
// 程式的主體
var todoItem = new TodoItem('...')
}
function TodoItem(title, id) {
// TodoList 的小單元叫做 TodoItem,然後定義各種 TodoItem 的屬性
this.title = title;
this.id = id;
...
return this
}

先定義好每個 TodoItem 裡面應該要有 title(內容) …等各式獨特的屬性。

除此之外,還需要一個儲存每一個 todoItem 和紀錄 id(編號)的地方:

var general = {
// 儲存每個 todoItem 的陣列
todos: [],
//從 0 開始計算的編號
globalID: 0
}

賦予程式更多的動作

這邊筆記一下,添加動作的寫法不只一種,以下兩種寫法功能上是一樣的:(不過意義上不同)

function Test() {
this.doSomething = function() {...}
}
Test.prototype.doSomething = function() {...}

前台的結構

接著,要建構前台能夠看得到的單位,預期應該是要這樣子的 HTML 結構:

前台看到的結構
<div>
<input type="text" \>
<button>產生todoItem</button>
<ul>
// TodoItem 的前台元素
<li>
<input type="checkbox" id="t1" \>
<label for="t1">TodoItem的內容</label>
</li>
// TodoItem 的前台元素
</ul>
</div>

結構和步驟大致上可以拆成這樣:
1. TodoList 這邊要建立一個 <ul> 來放置 TodoItem 的 <li>。
2. 透過 <button> 取得 <input> 的值作為 TodoItem 的內容。
3. TodoItem 的內容放到 <label> 裡面,並且對應 checkbox 的 id。

因此要擴展 TodoList 和 TodoItem 「建立前台元素」的動作:

TodoList 的前台元素:

function TodoList() {
...
this.$elem = this.buildElem()
}
TodoList.prototype.buildElem = function() {
// 建立 TodoList 需要用到的前台元素
var $ul = document.createElement('ul'),
$btn = document.createElement('button'),
$input = document.createElement('input'),
$container = document.createElement('div')
// 做出可輸入的 input text 區
$input.setAttribute('type', 'text')
// 把這些前台元素都幫起來放到 $container 裡面
$container.append($input)
$container.append($btn)
$container.append($ul)
return $container
}

TodoItem 的前台元素:

function TodoItem(title, id) {
...
this.$elem = this.buildElem()
}
TodoItem.prototype.buildElem = function() {
// 建立 TodoItem 需要用到的元素
var $li = document.createElement('li'),
$label = document.createElement('label'),
$checkbox = document.createElement('input')
// 放入 <input> 的內容
$label.textContent = title
// 給 checkbox 和 label 相同的編號
$label.setAttribute('for', id)
$checkbox.setAttribute('type', 'checkbox')
$checkbox.setAttribute('id', id)
// 把所有前台元素放到 <li> 裡面
$li.append($checkbox)
$li.append($label)
return $li
}

賦予更多事件或動作

賦予這些元素各種動作,讓 <button> 按下之後取得 <input> 的值,並且以此創造出 new TodoItem 實例。

function TodoList() {
...
this.bindEvents()
}
TodoList.prototype.bindEvents = function() {
// 找到元素中的 <button>,並賦予他 onCreateTodo 的動作
var button = this.$elem.querySelector('button')
button.addEventListener('click', this.onCreateTodo.bind(this))
}
TodoList.prototype.onCreateTodo = function() {
var input = this.$elem.querySelector('input')
var ul = this.$elem.querySelector('ul')
// 取得 <input> 的內容
var title = input.value
// 從 general.globalID 取得目前的編號,並且 +1
var id = general.globalID ++
// newTodo 就是一個新的 TodoItem,並且把 id 和 title 放進去
var newTodo = new TodoItem(id, title)
// 把這個 newTodo 的前台元素新增到 <ul> 裡面
ul.appendChild(newTodo.$elem)
// 把新的 newTodo 存到 general.todos
general.todos.push(newTodo)
}

最後步驟

如此一來就完成了一個系列的程式動作了,最後別忘了 TodoList() 也是一個物件,也必須創造出他的實例:

var todoList = new TodoList()
document.body.appendChild(todoList.$elem)

這樣就算是完成了一個極簡版的 TodoList 了!https://glennjong.github.io/noob.todolist/easy.html

整理一下

  1. 當按下了按鈕, 就會創立 TodoItem 實例

以上,是以一個初學者的程度寫出來的簡易 todoList,了解了物件導向的作法後,就能夠更輕易地擴充各種功能,像是刪除、暫存…之類更完整的功能,例如:
https://glennjong.github.io/noob.todolist/

若有任何建議歡迎與我交流XD

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade