總結(jié):傳統(tǒng)前端開(kāi)發(fā)模型
到此為止,我們已經(jīng)學(xué)習(xí)了HTML+CSS+JS這三大傳統(tǒng)前端技術(shù),這一次課我們停下來(lái)做一個(gè)簡(jiǎn)單的總結(jié)和回顧。
基于這三大傳統(tǒng)技術(shù)開(kāi)發(fā)網(wǎng)頁(yè)的流程一般是這樣的:
- 使用HTML定義頁(yè)面的結(jié)構(gòu)和組成
- 使用CSS優(yōu)化頁(yè)面的顯示和布局
- 使用JS完成網(wǎng)頁(yè)的交互功能
現(xiàn)在讓我們利用所學(xué)的知識(shí)來(lái)嘗試完成一個(gè)簡(jiǎn)單的demo應(yīng)用,跟著下面的教程一步一步來(lái),從中體會(huì)一個(gè)應(yīng)用的設(shè)計(jì)和開(kāi)發(fā)流程。
綜合實(shí)例:TODO LIST
DEMO:寫(xiě)一個(gè)網(wǎng)頁(yè)版本的TODO LIST,可以實(shí)現(xiàn)待辦事項(xiàng)的提醒。
這個(gè)DEMO將會(huì)貫穿我們整套教程,在學(xué)習(xí)了后續(xù)知識(shí)之后我們將會(huì)優(yōu)化它的頁(yè)面顯示,給它加入用戶(hù)和分類(lèi)系統(tǒng),最終甚至上線(xiàn)成為一個(gè)真正的web應(yīng)用。
分析需求
- 顯示TODO LIST
- 添加一個(gè)TODO
- 刪除一個(gè)已經(jīng)存在的TODO(標(biāo)記為已完成)
頁(yè)面設(shè)計(jì)
我們可以參考一下成型的TODO LIST類(lèi)應(yīng)用長(zhǎng)什么樣子:
首先是蘋(píng)果OSX系統(tǒng)內(nèi)置的reminder應(yīng)用:
接下來(lái)是番茄土豆
可以看到大致都差不多,頁(yè)面上主要就是一個(gè)列表,一個(gè)輸入框加上一些輔助按鈕
現(xiàn)在我們就利用HTML把這個(gè)頁(yè)面給他簡(jiǎn)單的復(fù)現(xiàn)出來(lái),大概的代碼如下(index.html
):
<div class="container">
<div class="header">
<input type="text" id="new-todo" class="new-todo-input">
<button id="add-new" class="btn-add">+添加</button>
</div>
<div class="list" id="todo-list">
<h3>TODO</h3>
<h4><span>待辦事項(xiàng)1</span><button class="btn-del">刪除</button></h4>
<h4><span>待辦事項(xiàng)2</span><button class="btn-del">刪除</button></h4>
<h4><span>待辦事項(xiàng)3</span><button class="btn-del">刪除</button></h4>
</div>
</div>
首先我們放一個(gè)最大最頂級(jí)的div,class為container,這樣方便后面管理整個(gè)應(yīng)用的樣式,把輸入框和列表拆分開(kāi)來(lái),把元素做一個(gè)簡(jiǎn)單的劃分和包裝,然后大概得到下面這個(gè)頁(yè)面
修改樣式和布局
大體的框架已經(jīng)出來(lái)了,不過(guò)這個(gè)不太好看,我們應(yīng)用CSS稍稍的布局一下它,現(xiàn)在讓我們創(chuàng)建一個(gè)index.css
文件并引入它,添加下面的內(nèi)容
body {
font-weight: lighter;
font-size: 20px
}
.container {
text-align: center;
margin: auto
}
.header {
width: 50%
}
.list {
width: 50%;
}
.new-todo-input {
height: 24px;
width: 300px;
}
input {
border: 1px solid gray;
-webkit-border-radius: 3px;
-moz-border-radius:5px
}
button {
background-color: white;
border: 1px solid gray;
-webkit-border-radius: 5px;
-moz-border-radius:5px;
font-size: 16px;
font-weight: lighter
}
.btn-add {
height: 28px;
width: 80px;
}
.btn-del {
margin-left: 20px;
background-color: red;
color: white
}
h4 {
font-size: 20px;
font-weight: lighter
}
h3 {
font-weight: 200
}
注意這里的幾個(gè)重要屬性:
-
font-weight:lighter
可以讓字體變得更纖細(xì),好看一些 -
-webkit-border-radius
和-moz-border-radius
可以在chrome和firefox瀏覽器中引入圓角矩形
然后我們得到布局優(yōu)化過(guò)后的界面:
鑒于本人前端能力有限,只能優(yōu)化到這種地步了(其實(shí)還是蠻丑的),有能力的同學(xué)不妨自己嘗試優(yōu)化一下頁(yè)面,此外,在后面的前端相關(guān)課程中我們也會(huì)通過(guò)組件庫(kù)來(lái)優(yōu)化頁(yè)面,你不必?fù)?dān)心因?yàn)椴粫?huì)寫(xiě)CSS而做不出好看的頁(yè)面。
實(shí)現(xiàn)功能
現(xiàn)在讓我們進(jìn)入最核心的部分,實(shí)現(xiàn)功能。大概分析一下我們這里有兩個(gè)功能,一是創(chuàng)建,二是刪除。
-
創(chuàng)建:
獲取輸入框的內(nèi)容,創(chuàng)建一個(gè)h4節(jié)點(diǎn),然后把內(nèi)容填充上并添加刪除按鈕,最后添加到todo-list節(jié)點(diǎn)下。
-
刪除:
從list中移除指定的todo-item的h4節(jié)點(diǎn)
為了追蹤todo-item,我們還得給每個(gè)item指定一個(gè)id,不妨就用todo-item-1
,todo-item-2
這樣的方式吧。
現(xiàn)在我們創(chuàng)建一個(gè)index.js
文件并引入。現(xiàn)在想想js里面需要寫(xiě)些什么?
- 首先我們需要兩個(gè)函數(shù)用來(lái)實(shí)現(xiàn)創(chuàng)建和刪除的功能
- 我們需要一個(gè)能夠動(dòng)態(tài)生成唯一id的方法,在這里我采用了一個(gè)簡(jiǎn)單的方式,那就是定義一個(gè)全局變量,然后每次需要生成新節(jié)點(diǎn)的時(shí)候讓他自增一下,就可以得到一個(gè)新的id了
接下來(lái)是index.js
里的內(nèi)容
var todoCount = 0;
function addNewTodo() {
item = document.getElementById('new-todo').value;
itemId = ++todoCount;// 為新的待辦事項(xiàng)設(shè)置id
// 創(chuàng)建新的節(jié)點(diǎn)
var newItem = document.createElement('h4');
newItem.setAttribute('id','todo-item-'+itemId);
var newSpan = document.createElement('span');
newSpan.innerText = item;
var newButton = document.createElement('button');
newButton.className = 'btn-del';
// 綁定點(diǎn)擊事件
newButton.setAttribute('onclick','deleteTodo('+itemId+')');
newButton.innerText = '刪除';
newItem.appendChild(newSpan);
newItem.appendChild(newButton);
var list = document.getElementById('todo-list');
list.appendChild(newItem);
}
function deleteTodo(id) {
// DOM節(jié)點(diǎn)要求必須找到所要?jiǎng)h除的節(jié)點(diǎn)的父節(jié)點(diǎn)才能將其刪除,所以使用了parentNode來(lái)獲取父節(jié)點(diǎn)
var target = document.getElementById('todo-item-'+id);
var parent = target.parentNode;
parent.removeChild(target);
}
別忘了給頁(yè)面上那個(gè)添加按鈕綁定onclick事件。
至此這個(gè)簡(jiǎn)單的應(yīng)用就完成了。你也可以嘗試給他添加一些功能(比如顯示待辦事項(xiàng)的添加時(shí)間)。
這個(gè)demo的源碼已經(jīng)同步到github上,需要的話(huà)可以點(diǎn)擊下面的鏈接進(jìn)行參考:
不足和改進(jìn)空間
一個(gè)簡(jiǎn)單的TODO LIST應(yīng)用完成了,但是作為一個(gè)應(yīng)用它還存在很多的不足:
-
不能保存狀態(tài),頁(yè)面關(guān)閉后所有的內(nèi)容都會(huì)被重置。
我們可以通過(guò)添加后端服務(wù)的方式來(lái)解決,將數(shù)據(jù)保存到服務(wù)器的數(shù)據(jù)庫(kù)上即可。
另一種優(yōu)化思路是利用瀏覽器的localStorage
,這相當(dāng)于是一個(gè)瀏覽器內(nèi)置的一個(gè)小型緩存區(qū),在關(guān)閉瀏覽器前都會(huì)被保存。 刪除應(yīng)該有一個(gè)提示框,防止誤操作,可以通過(guò)
confirm()
函數(shù)來(lái)輔助頁(yè)面太丑了,這個(gè)可以通過(guò)后期引庫(kù)的方式改善,有能力的同學(xué)也可以自己修改CSS
前端發(fā)展的現(xiàn)狀和注意事項(xiàng)
至此,前端認(rèn)知部分的內(nèi)容就算講解完畢。讓我們來(lái)分析一下目前這種頁(yè)面構(gòu)造方式中存在的一些問(wèn)題:
- 當(dāng)頁(yè)面變得很大的時(shí)候,HTML代碼可能會(huì)十分冗長(zhǎng),這將大大降低可讀性和可維護(hù)性
- 用CSS來(lái)定制樣式比較繁瑣,如果所有的頁(yè)面樣式都自己定義實(shí)在太費(fèi)時(shí)費(fèi)力了
前端現(xiàn)在主要通過(guò)組件化和庫(kù)來(lái)解決上面兩個(gè)問(wèn)題。
組件化就是把頁(yè)面拆解成組件,渲染的時(shí)候再把組件拼接在一起,這樣只用維護(hù)組件就可以了,增加了復(fù)用性和可維護(hù)性。
同時(shí)出現(xiàn)了許多的組件庫(kù)和樣式庫(kù),通過(guò)外鏈的方式引入css和js就可以使用,非常方便(比如bootstrap,你可以試著用它來(lái)優(yōu)化上面那個(gè)demo的頁(yè)面)。
目前的前端開(kāi)發(fā)工作主要如下:
- 通過(guò)組件組織頁(yè)面結(jié)構(gòu)
- 調(diào)整頁(yè)面樣式
- 編寫(xiě)頁(yè)面組件
- 編寫(xiě)頁(yè)面邏輯
- 管理網(wǎng)絡(luò)請(qǐng)求
三大技術(shù)棧
- react
- vue
- angularJS
注意這三大技術(shù)棧基本是互不兼容的,各自擁有一套技術(shù)體系和生態(tài)圈。
下面對(duì)于想要學(xué)習(xí)前端的同學(xué)給出一些注意事項(xiàng):
- 前端的技術(shù)迭代非常快,各種框架和腳手架層出不窮,幾周甚至幾天就有新的技術(shù)涌現(xiàn),因此要時(shí)刻關(guān)注最新動(dòng)態(tài),學(xué)習(xí)新技術(shù)。
- JS是目前整個(gè)前端生態(tài)圈的基石,因此一定要牢固掌握,并且JS的版本也在不斷迭代,請(qǐng)至少學(xué)習(xí)ES6版本及以后的JS。
- 因?yàn)楦鱾€(gè)框架對(duì)JS包裝的十分嚴(yán)重,在使用不同的框架時(shí)你可能感覺(jué)在使用兩種不同的語(yǔ)言。
后續(xù)的應(yīng)用篇中將會(huì)進(jìn)一步給出一套前端的學(xué)習(xí)路徑和課程,敬請(qǐng)關(guān)注。