Web前端技術由html、css和javascript三大部分構成,是一個龐大而複雜的技術體系,其複雜程度不低於任何一門後端語言。而我們在學習它的時候往往是先從某一個點切入,然後不斷地接觸和學習新的知識點,因此對於初學者很難理清楚整個體系的脈絡結構。本文將對Web前端知識體系進行簡單的梳理,對應的每個知識點點到為止,不作詳細介紹。目的是幫助大家審查自己的知識結構是否完善,如有遺漏或不正確的地方,希望共勉。
JAVASCRIPT 篇
0、基礎語法
Javascript基礎語法包括:變數定義、資料型別、迴圈、選擇、內建物件等。
資料型別有string,number,boolean,null,undefined,object等。其中,string,number和boolean是基礎型別,null和undefined是JS中的兩個特殊型別,object是引用型別。
Javascript可以通過typeof來判斷基礎資料型別,但不能夠準確判斷引用型別, 因此需要用到另外一個方法,那就是Object的toString,關於資料型別及其判斷可以參考以下部落格:資料型別詳解 和 判斷JS資料型別的四種方法
JS常用的內建物件有Date、Array、JSON,RegExp等。 一般來講,Date和Array用的最頻繁,JSON可以對物件和陣列進行序列化和反序列化,還有一個作用就是實現物件的深拷貝。
RegExp即正規表示式,是處理字串的利器。 關於資料型別和正規表示式的介紹可以參考部落格:ES5對陣列增強的9個API 和 JS正規表示式精簡
1、函式原型鏈
Javascript雖然沒有繼承概念,但Javascript在函式Function物件中建立了原型物件prototype,並以Function物件為主線,從上至下,在內部構建了一條原型鏈。
簡單來說就是建立了變數查詢機制,當訪問一個物件的屬性時,先查詢物件本身是否存在,如果不存在就去該物件所在的原型連上去找,直到Object物件為止,如果都沒有找到該屬性才會返回undefined。
因此我們經常會利用函式的原型機制來實現JS繼承。關於函式原型鏈可參考部落格:JS原型物件和原型鏈
2、函式作用域
函式作用域就是變數在宣告它們的函式體以及這個函式體巢狀的任意函式體內都是有定義的。在JS中沒有會塊級作用域,只有函式作用域,因此JS中還存在著另外一種怪異現象,那就是變數提升。關於作用域的介紹請參考部落格:函式的作用域和作用域鏈
3、函式指標 this
this 存在於函式中,它指向的是該函式在執行時被呼叫的那個物件。在實際專案中,遇到this的坑比較多,因此需要對this作深入的理解。
Function物件還提供了call、apply和bind等方法來改變函式的this指向,其中call和apply主動執行函式,bind一般在事件回撥中使用,而call和apply的區別只是引數的傳遞方式不同。關於call,apply和bind的使用者請參考部落格:詳解JS的call,apply和bind
4、建構函式 new
JS中的函式即可以是建構函式又可以當作普通函式來呼叫,當使用new來建立物件時,對應的函式就是建構函式,通過物件來呼叫時就是普通函式。
普通函式的建立有:顯式宣告、匿名定義、new Function() 等三種方式。
當通過new來建立一個新物件時,JS底層將新物件的原型鏈指向了建構函式的原型物件,於是就在新物件和函式物件之間建立了一條原型鏈,通過新物件可以訪問到函式物件原型prototype中的方法和屬性。new的詳細介紹請參考部落格:理解JS中的new運算子
5、閉包
閉包其實是一個主動執行的程式碼塊,這個程式碼塊的特殊之處是可以永久儲存區域性變數,但又不汙染全域性變數,可以形成一個獨立的執行過程,因此我們經常用閉包來定義元件。關於閉包的介紹請參考:乾貨分享:讓你分分鐘學會JS閉包
6、單執行緒和非同步佇列
setTimeout和setInterval是JS內建的兩個定時器,使用很簡單,但這兩個方法背後的原理卻不簡單。
我們知道,JS是單執行緒語言,在瀏覽器中,當JS程式碼被載入時,瀏覽器會為其分配一個主執行緒來執行任務(函式),主執行緒會形成一個全域性執行環境,執行環境採用棧的方式將待執行任務按順序依次來執行。
但在瀏覽器中有一些任務是非常耗時的,比如http請求、定時器、事件回撥等,為了保證其他任務的執行效率不被影響,JS在執行環境中維護了一個非同步佇列(也叫工作執行緒),並將這些任務放入佇列中進行等待,這些任務的執行時機並不確定,只有當主執行緒的任務執行完成以後,才會去檢查非同步佇列中的任務是否需要開始執行。這就是為什麼setTimeout(fn,0) 始終要等到最後執行的原因。關於單執行緒和非同步佇列問題請參考:setTimeout(0)
7、非同步通訊 Ajax技術
Ajax是瀏覽器專門用來和伺服器進行互動的非同步通訊技術,其核心物件是XMLHttpRequest,通過該物件可以建立一個Ajax請求。為了防止XSS攻擊,瀏覽器對Ajax做了限制,不允許Ajax跨域請求伺服器,就是隻能訪問當前域名下的url。
當然,如果確信你的站點不存在跨域的風險,可以在服務端主動開啟跨域請求。 也可以直接通過CORS或JSONP來實現。
JSONP是利用指令碼(script)跨域能力來模擬Ajax請求。
CORS是一個W3C標準,全稱是”跨域資源共享”(Cross-origin resource sharing)。它允許瀏覽器向跨源伺服器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。 關於CORS的介紹請參考:跨域資源共享 CORS 詳解
8、DOM物件 document
document物件裡儲存著整個web頁面dom結構,在頁面上所有的元素最終都會對映為一個dom物件。 document也提供了很多api來查詢特定的dom物件,比如getElementById,querySelector等等。
9、事件系統 Event
事件是使用者與頁面互動的基礎,到目前為止,DOM事件從PC端的 滑鼠事件(mouse) 發展到移動端的 觸控事件(touch) 和 手勢事件(guesture)
由於DOM結構可能會多層巢狀,因此也衍生出了兩種事件流:事件捕獲和事件冒泡,後者最常用。利用事件冒泡機制可以實現很多功能,比如頁面點選統計。關於兩種事件流的介紹請參考:事件冒泡和捕獲
除此之外,在頁面初始化、滾動、隱藏、返回等操作時分別內建了onload/onDOMContentLoaded、onscroll、onvisibility和onhashchange等事件,如果想要捕獲這些事件,需要通過addEventLisener/attachEvent來進行繫結。
10、全域性物件 window
在JS中,當一段JS程式碼在瀏覽器中被載入執行,JS引擎會在記憶體中構建一個全域性執行環境,執行環境的作用是保證所有的函式能按照正確的順序被執行,而window物件則是這個執行環境中的一個全域性物件,window物件中內建了很多操作api和物件,document物件就是其中一個。關於JS執行環境的介紹請參考部落格:深入理解JS執行細節
CSS 篇
css是用來對html進行修飾的一門語言。
1、選擇器
css的選擇器有很多種,常用的有類選擇器、標籤選擇器、ID選擇器、後代選擇器、群組選擇器、偽類選擇器(before/after)、兄弟選擇器(+~)、屬性選擇器等等。
2、定位
定位一般有相對定位(relative)、絕對定位(absolute)、固定定位(fixed),relative和absolute在移動端用的最多,fixed 在移動端有相容性問題,因此不推薦使用,在移動端替代fixed的方案是 absolute+內部滾動。
3、浮動
設定float為left或right,就能使該元素脫離文件流,向左或向右浮動。一般在做宮格模式佈局時會用到,如果子元素全部設定為浮動,則父元素是塌陷的,這時就需要清除浮動,清除浮動的方法也很多,常用的方法是在元素末尾加空元素設定clear:both, 更高階一點的就給父容器設定before/after來模擬一個空元素,還可以直接設定overflow:auto/hidden。除過浮動可以實現宮格模式,行內盒子(inline-block)和table也可以。
4、盒子模型
盒子模型是css最重要的一個概念,也是css佈局的基石。 常見的盒子模型有塊級盒子(block)和行內盒子(inline-block),盒子最關鍵的幾個屬性包括margin、border、padding和content,這幾個元素可以設定盒子和盒子之間的關係以及盒子和內容之間的關係。還有一個問題是計算盒子的大小,需要注意的是,box-sizing屬性的設定會影響盒子的width和height。只有普通文件流中塊框的垂直外邊距才會發生外邊距合併。行內框、浮動框或絕對定位之間的外邊距不會合並。
5、Flex佈局
Flex佈局的容器是一個伸縮容器,首先容器本身會更具容器中的元素動態設定自身大小;然後當Flex容器被應用一個大小時(width和height),將會自動調整容器中的元素適應新大小。Flex容器也可以設定伸縮比例和固定寬度,還可以設定容器中元素的排列方向(橫向和縱向)和是否支援元素的自動換行。有了這個神器,做頁面佈局的可以方便很多了。注意,設為Flex佈局以後,子元素的float、clear和vertical-align屬性將失效。
6、transition(過渡) 和 transform(旋轉)
應用transform可以對元素進行平移(translate)、旋轉(rotate)、放大縮小(scale)、傾斜(skew)等處理,而transition使css屬性值(包括transform)在一段時間內平滑的過渡。使用transition和transform就可以實現頁面的滑動切換效果。
7、動畫 Animation
Animation首先需要設定一個動畫函式,然後以這個動畫的方式來改變元素的css屬性之的變化,動畫可以被設定為永久迴圈演示。 和transition相比,animation設定動畫效果更靈活更豐富,二者還有一個區別是:transition只能通過主動改變元素的css值才能觸發動畫效果,而animation一旦被應用,就開始執行動畫。
8、Sprite圖
對於大型站點,為了減少http請求的次數,一般會將常用的小圖示排到一個大圖中,頁面載入時只需請求一次網路, 然後在css中通過設定background-position來控制顯示所需要的小圖示。
9、字型圖示 iconfont
所謂字型圖示就是將常用的圖示轉化為字型資源存在檔案中,通過在CSS中引用該字型檔案,然後可以直接通過控制字型的css屬性來設定圖示的樣式。
HTML 篇
1、Web語義化 和 SEO
html 常規標籤有html,head,body,div,span,table,ul,ol,dl,p,b,h1~h6,strong,form,input,img,em,i 等等,另外html5 還新增了很多語義化的標籤,比如header,acticle,aside,section,footer,audio,radio 等等。
Web語義化是指使用語義恰當的標籤,使頁面有良好的結構,頁面元素有含義,能夠讓人和搜尋引擎都容易理解。
SEO是指在瞭解搜尋引擎自然排名機制的基礎之上,對網站進行內部及外部的調整優化,改進網站在搜尋引擎中關鍵詞的自然排名,獲得更多的展現量,吸引更多目標客戶點選訪問網站,從而達到網際網路營銷及品牌建設的目標。
搜尋引擎通過爬蟲技術獲取的頁面就是由一堆html標籤組成的程式碼,,人可以通過視覺化的方式來判斷頁面上哪些內容是重點,而機器做不到。 但搜尋引擎會根據標籤的含義來判斷內容的權重,因此,在合適的位置使用恰當的標籤,使整個頁面的語義明確,結構清晰,搜尋引擎才能正確識別頁面中的重要內容,並予以較高的權值。比如h1~h6這幾個標籤在SEO中的權值非常高,用它們作頁面的標題就是一個簡單的SEO優化。
2、頁面渲染機制
頁面渲染就是瀏覽器的渲染引擎將html程式碼根據CSS定義的規則顯示在瀏覽器視窗中的過程。大致工作原理如下:
- 使用者輸入網址,瀏覽器向伺服器發出請求,伺服器返回html檔案;
- 渲染引擎開始載入html程式碼,並將HTML中的標籤轉化為DOM節點,生成DOM樹;
- 如果中引用了外部css檔案,則發出css檔案請求,伺服器返回該檔案;
- 如果中引用了外部js檔案,則發出js檔案請求,伺服器返回該檔案後開始執行;
- 渲染引擎繼續載入html中的部分的程式碼,並開始解析前面返回的css檔案,然後根據css選擇器計算出節點的樣式,建立渲染樹;
- 從根節點遞迴呼叫,計算每一個元素的大小、位置等,給每個節點所應該出現在螢幕上的精確座標;
- 如果body中的引用了圖片資源,則立即向伺服器發出請求,此時渲染引擎不會等待圖片下載完畢,而是繼續渲染後面的程式碼;
- 伺服器返回圖片檔案,由於圖片佔用了一定面積,影響了後面段落的排版,因此引擎需要回過頭來重新渲染這部分程式碼;
- 如果此時js指令碼中執行了style.display=”none”, 佈局被改變,引擎也需要重新渲染這部分程式碼;
- 直到為止,頁面渲染完畢。
3、重繪和迴流
當渲染樹中的一部分(或全部)因為元素的規模尺寸,佈局,隱藏等改變而需要重新構建。這就稱為迴流。比如上面的img檔案載入完成後就會引起迴流,每個頁面至少需要一次迴流,就是在頁面第一次載入的時候。
當渲染樹中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響佈局的,比如background-color。則就叫稱為重繪。
從上面可以看出,迴流必將引起重繪,而重繪不一定會引起迴流。
會引起重繪和迴流的操作
- 新增、刪除元素(迴流+重繪)
- 隱藏元素,display:none(迴流+重繪),visibility:hidden(只重繪,不迴流)
- 移動元素,比如改變top,left,transform的值,或者移動元素到另外一個父元素中。(重繪+迴流)
- 對style的操作(對不同的屬性操作,影響不一樣)
- 還有一種是使用者的操作,比如改變瀏覽器大小,改變瀏覽器的字型大小等(迴流+重繪)
4、本地儲存
本地儲存最原始的方式就是 cookie,cookie 是存放在本地瀏覽器的一段文字,資料以鍵值對的形式儲存,可以設定過期時間。 但是 cookie 不適合大量資料的儲存,因為每請求一次頁面,cookie 都會傳送給伺服器,這使得 cookie 速度很慢而且效率也不高。因此cookie的大小被限制為4k左右(不同瀏覽器可能不同,分HOST),如下所示:
- Firefox和Safari允許cookie多達4097個位元組,包括名(name)、值(value)和等號。
- Opera允許cookie多達4096個位元組,包括:名(name)、值(value)和等號。
- Internet Explorer允許cookie多達4095個位元組,包括:名(name)、值(value)和等號。
在所有瀏覽器中,任何cookie大小超過限制都被忽略,且永遠不會被設定。
html5提供了兩種在客戶端儲存資料的新方法:localStorage 和 sessionStorage, 它們都是以key/value 的形式來儲存資料,前者是永久儲存,後者的儲存期限僅限於瀏覽器會話(session),即當瀏覽器視窗關閉後,sessionStorage中的資料被清除。
localStorage的儲存空間大約5M左右(不同瀏覽器可能不同,分 HOST),這個相當於一個5M大小的前端頁面的資料庫,相比於cookie可以節約頻寬,但localStorage在瀏覽器隱私模式下是不可讀取的,當儲存資料超過了localStorage的儲存空間後會丟擲異常。
此外,H5還提供了逆天的websql和indexedDB,允許前端以關係型資料庫的方式來儲存本地資料,相對來說,這個功能目前應用的場景比較少,此處不作介紹。
5、瀏覽器快取機制
瀏覽器快取機制是指通過 HTTP 協議頭裡的 Cache-Control(或 Expires)和 Last-Modified(或 Etag)等欄位來控制檔案快取的機制。
Cache-Control 用於控制檔案在本地快取有效時長。最常見的,比如伺服器回包:Cache-Control:max-age=600 表示檔案在本地應該快取,且有效時長是600秒(從發出請求算起)。在接下來600秒內,如果有請求這個資源,瀏覽器不會發出 HTTP 請求,而是直接使用本地快取的檔案。
Last-Modified 是標識檔案在伺服器上的最新更新時間。下次請求時,如果檔案快取過期,瀏覽器通過 If-Modified-Since 欄位帶上這個時間,傳送給伺服器,由伺服器比較時間戳來判斷檔案是否有修改。如果沒有修改,伺服器返回304告訴瀏覽器繼續使用快取;如果有修改,則返回200,同時返回最新的檔案。
Cache-Control 通常與 Last-Modified 一起使用。一個用於控制快取有效時間,一個在快取失效後,向服務查詢是否有更新。
Cache-Control 還有一個同功能的欄位:Expires。Expires 的值一個絕對的時間點,如:Expires: Thu, 10 Nov 2015 08:45:11 GMT,表示在這個時間點之前,快取都是有效的。
Expires 是 HTTP1.0 標準中的欄位,Cache-Control 是 HTTP1.1 標準中新加的欄位,功能一樣,都是控制快取的有效時間。當這兩個欄位同時出現時,Cache-Control 是高優化級的。
Etag 也是和 Last-Modified 一樣,對檔案進行標識的欄位。不同的是,Etag 的取值是一個對檔案進行標識的特徵字串。在向伺服器查詢檔案是否有更新時,瀏覽器通過 If-None-Match 欄位把特徵字串傳送給伺服器,由伺服器和檔案最新特徵字串進行匹配,來判斷檔案是否有更新。沒有更新回包304,有更新回包200。Etag 和 Last-Modified 可根據需求使用一個或兩個同時使用。兩個同時使用時,只要滿足基中一個條件,就認為檔案沒有更新。
另外有兩種特殊的情況:
- 手動重新整理頁面(F5),瀏覽器會直接認為快取已經過期(可能快取還沒有過期),在請求中加上欄位:Cache-Control:max-age=0,發包向伺服器查詢是否有檔案是否有更新。
- 強制重新整理頁面(Ctrl+F5),瀏覽器會直接忽略本地的快取(有快取也會認為本地沒有快取),在請求中加上欄位:Cache-Control:no-cache(或 Pragma:no-cache),發包向服務重新拉取檔案。
6、History路由機制
使用者訪問網頁的歷史記錄通常會被儲存在一個類似於棧物件中,即history物件,點選返回就出棧,跳下一頁就入棧。 它提供了一些方法來操作頁面的前進和後退:
- window.history.back() 返回到上一個頁面
- window.history.forward() 進入到下一個頁面
- window.history.go([delta]) 跳轉到指定頁面
HTML5 對History Api 進行了增強,新增了兩個Api和一個事件,分別是pushState、replaceState 和 onpopstate
pushState是往history物件裡新增一個新的歷史記錄,即壓棧。
replaceState 是替換history物件中的當前歷史。
當點選瀏覽器後退按鈕或js呼叫history.back都會觸發onpopstate事件, 與其類似的還有一個事件: onhashchange 。
onhashchange是老API, 瀏覽器支援度高, 本來是用來監聽hash變化的, 但可以被利用來做客戶端前進和後退事件的監聽,onpopstate是專門用來監聽瀏覽器前進後退的, 不僅可以支援hash, 非hash的同源url也支援。
7、HTML5離線快取
HTML5離線快取又叫Application Cache,是從瀏覽器的快取中分出來的一塊快取區,如果要在這個快取中儲存資料,可以使用一個描述檔案(manifest file),列出要下載和快取的資源。
manifest 檔案是簡單的文字檔案,它告知瀏覽器被快取的內容(以及不快取的內容)。manifest 檔案可分為三個部分:
– CACHE MANIFEST – 在此標題下列出的檔案將在首次下載後進行快取
– NETWORK – 在此標題下列出的檔案需要與伺服器的連線,且不會被快取
– FALLBACK – 在此標題下列出的檔案規定當頁面無法訪問時的回退頁面(比如 404 頁面)
離線快取為應用帶來三個優勢:
- 離線瀏覽 – 使用者可在應用離線時使用它們
- 速度 – 已快取資源載入得更快
- 減少伺服器負載 – 瀏覽器將只從伺服器下載更新過或更改過的資源。
8、Canvas和SVG
Canvas 通過Javascript 來繪製 2D 圖形。Canvas 是逐畫素進行渲染的。在 Canvas 中,一旦圖形被繪製完成,它就不會繼續得到瀏覽器的關注。如果其位置發生變化,那麼整個場景也需要重新繪製,包括任何或許已被圖形覆蓋的物件。
SVG 是一種使用 XML 描述 2D 圖形的語言。SVG 基於 XML,這意味著 SVG DOM 中的每個元素都是可用的。你可以為某個元素附加 JavaScript 事件處理器。在 SVG 中,每個被繪製的圖形均被視為物件。如果 SVG 物件的屬性發生變化,那麼瀏覽器能夠自動重現圖形。
Canvas和SVG相比,canvas更依賴於解析度,不支援事件處理器,文字渲染能力弱,比較適合密集型遊戲,其中的許多物件會被頻繁繪製,而svg則比較適用於類似谷歌地圖帶有大型渲染區域的應用程式。