網頁
什么是網頁?
- 網頁 =
Html+CSS+JavaScript
-
Html
是網頁的內容 -
CSS
是網頁的樣式 -
JavaScript
是網頁的行為
-
每個學習編程語言的第一個編程肯定是打印出"Hello World"來看看JavaScript是怎么實現的.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>認識js</title>
</head>
<body>
<script>
document.write("Hello World") //會在頁面中出現Hello World
</script>
</body>
</html>
來看一下JavaScript的發展歷史
誰也想不到,1995年被當做營銷策略推出的JavaScript語言,在2017年成為了最受歡迎平臺(web)上的核心語言。JavaScript現在不僅可以在瀏覽器中運行,它還被用作開發桌面和手機應用,用于嵌入式設備,甚至NASA還拿它來設計太空組件。
發展
JS標準制定簡史(簡略)
- 只花了10天時間 Brendan 就開發完成了當時被稱作Mocha的初版 JavaScript 原型,這個新語言類似 Scheme ,它把函數當做一等公民,并以原型鏈為其核心。那時候的JS比較簡陋,沒有數組和字面量的對象的概念,所有的報錯都只能通過丑陋的alert展示,缺乏異常處理機制,出錯時很多運算的結果會是NaN或undefined。
- 1995年9月,網景公司發布了Netscape Navigator 2.0 beta版,JavaScript也被包裝為LiveScript一同面世。
- 1995年12月,Netscape Navigator 2.0 beta3發布,LiveScript在這時被改名為JavaScript(當時這個商標為Sun公司所有,現在屬甲骨文公司)。之后不久,網景推出了LiveWire,一種在其服務器(Netscape Enterprise Server)上的JavaScript實現1。
- 1996年開始,JS語言開始走上規范之路,它已ECMAScript的名字被標準化到ECMA-262規范,
- 1997年6月ECMA-262的第一版發布,之后一年中,規范依據ISO / IEC 16262國際標準進行了改進,并由ISO認證機構大量審查,1997年6月ECMAScript規范正式發布第二版。
- 1999年12月,第三版也發布了,這一版的規范帶來了正則表達式,switch,do/while,try/catch,Object#hasOwnProperty以及其它的一些改變
- 2007年,TC39委員會被迫分為兩部分,一部分負責ES3的漸進加強版ES3.1標準的制定,另一部分則負責重新設計改動巨大的ES4標準。2008年8月,ES3.1被認為是正確的選擇,隨后其更名為ES5,ES4也隨之被廢棄,不過值得慶幸的是 ES4 提出的很多新功能被融入到了 ES6 ,也有一些功能仍然在考慮之中,另一些則已被放棄,拒絕或撤回。兼容ES3.1 成為 ES4 標準提出的功能可能被采納的前提。
- 2009年12月,ES3發布10周年后,第五版ECMAScript才得以發布。這個版本把十年來各瀏覽器中已有的普遍實踐標準化了,新增了get
set
,改進了數組原型的函數式特征,原生支持了JSON的解析,提出了嚴格模式。 - 2015年6月,也就是ES5.1發布的四年后,TC39公布了JS語言有史以來最大的更新 ES6,其中包含了很多ES4中提出草案。本書,我們將深入探索ES6。
- ES6的發布是JS標準制定歷史上的一個重要里程碑。除了數十種引入注目的新功能,ES6 的發布也標志著 ECMAScript 標準將持續更新。
問題:ES3、ES5、ES6指什么?
- ES3 ES5 ES6 指的是不同的ECMAScript的版本
- 1999年12月,ECMAScript 3.0版發布,成為JavaScript的通行標準,得到了廣泛支持。
- 2009年12月,ECMAScript 5.0版正式發布
- 2015年6月,ECMAScript 6正式發布
參考:
瀏覽器的渲染機制
了解渲染機制之前,我們先了解幾個概念
- DOM:Document Object Model,瀏覽器將HTML解析成樹形的數據結構,簡稱DOM。
- CSSOM:CSS Object Model,瀏覽器將CSS代碼解析成樹形的數據結構。
- DOM 和 CSSOM 都是以
Bytes → characters → tokens → nodes → object model.
這樣的方式生成最終的數據 - Render Tree:DOM 和 CSSOM 合并后生成 Render Tree
瀏覽器渲染過程
渲染流程圖
渲染流程圖
- 用戶輸入一個
URL
的時候,瀏覽器就會發送一個請求,請求URL
對應的資源。 - 瀏覽器的
HTML
解析器會將這個文件解析,并且構建成一棵DOM
樹。(在生成DOM
的最開始階段(應該是Bytes → characters
后),并行發起css、
圖片、js
的請求,無論他們是否在HEAD
里。)- 注意:發起
js
文件的下載request
并不需要DOM
處理到那個script
節點,比如:簡單的正則匹配就能做到這一點,雖然實際上并不一定是通過正則:)。這是很多人在理解渲染機制的時候存在的誤區
- 注意:發起
- 在構建
DOM
樹的時候,遇到 js 和
CSS
元素,HTML解析器就換將控制權轉讓給JS解析器或者是CSS解析器。開始構建CSSOM
-
DOM
樹構建完之后,瀏覽器把DOM樹中的一些不可視元素去掉,然后與CSSOM
合成一棵render tree
。 -
Layout
:有了Render Tree
,瀏覽器已經能知道網頁中有哪些節點、各個節點的CSS定義以及他們的從屬關系。下一步操作稱之為Layout
,顧名思義就是計算出每個節點在屏幕中的位置。 -
Painting:Layout
后,瀏覽器已經知道了哪些節點要顯示(which nodes are visible
)、每個節點的CSS屬性是什么(their computed styles
)、每個節點在屏幕中的位置是哪里(geometry
)。就進入了最后一步:Painting
,按照算出來的規則,通過顯卡,把內容畫到屏幕上。
以上幾個步驟因為
DOM、CSSOM、Render Tree
都可能在第一次Painting
后又被更新多次,比如JS
修改了DOM
或者CSS
屬性。Layout
和Painting
也會被重復執行,除了DOM、CSSOM
更新的原因外,圖片下載完成后也需要調用Layout
和 `Painting來更新網頁
關于Repaint 和 Reflow
Repaint Reflow也就是中文中的重繪和回流
-
重繪(repaints)
是一個元素外觀的改變所觸發的瀏覽器行為,例如改變vidibility、outline、
背景色等屬性。瀏覽器會根據元素的新屬性重新繪制,使元素呈現新的外觀。重繪不會帶來重新布局,并不一定伴隨回流。 -
回流(reflow)
是更明顯的一種改變,可以理解為渲染樹需要重新計算。
引起
Repain
和Reflow
的一些操作
- 當你增加、刪除、修改
DOM
結點時,會導致Reflow 或 Repaint
。 - 當你移動
DOM
的位置,或是搞個動畫的時候。 - 當你修改
CSS
樣式的時候。 - 當你
Resize
窗口的時候(移動端沒有這個問題),或是滾動的時候。 - 當你修改網頁的默認字體時
- 注:
display:none
會觸發reflow
,而visibility:hidden
只會觸發repaint
,因為沒有發現位置變化。
- 注:
參考:
如何異步加載腳本
向
HTML
頁面中插入JavaScript
的方法,就是使用<script>
標簽,我們先來了解一下<script>
定義了6個屬性
-
async:
異步腳本可選,表示立即下載腳本,但不妨礙頁面中其他操作,只對外部腳本有效 -
defer:
延遲腳本可選.表示腳本可以延遲到文檔完全被解析和顯示之后再執行.只對外部腳本文件有效 -
charset:
可選,表示通過src
屬性指定的代碼的字符集,由于大多數瀏覽器會忽略這個值,因此屬性很少用 -
src:
可選,表示包含要執行的外部文件 -
language:
已廢棄 -
type:
可選,可以看成是language
的替代屬性
<script src="script.js"></script>
- 沒有
defer
或async
,瀏覽器會立即加載并執行指定的腳本,“立即”指的是在渲染該script
標簽之下的文檔元素之前,也就是說不等待后續載入的文檔元素,讀到就加載并執行
<script async src="script1.js"></script>
<script async src="script2.js"></script>
- 有
async
,加載和渲染后續文檔元素的過程將和 script.js 的加載與執行并行進行(異步)。 -
async
不保證按照它們的先后順與執行 - 異步腳本一定會在頁面的
load
事件前執行
<script defer src="script.js"></script>
- 有
defer
,加載后續文檔元素的過程將和 script.js 的加載并行進行(異步),但script.js
的執行要在所有元素解析完成之后,DOMContentLoaded
事件觸發之前完成。 - 腳本延遲到文檔解析和顯示后執行,有順序
解釋白屏和 FOUC(無樣式內容閃爍)
- fouc出現的條件
- 使用@import方法導入CSS時,此方式由于IE會先加載整個HTML文檔的DOM,然后再去導入外部的CSS文件,因此,在頁面DOM加載完成到CSS導入完成中間會有一段時間頁面上的內容是沒有樣式的,這段時間的長短跟網速,電腦速度都有關系。
- 將樣式表放在頁面底部
- 有幾個樣式表,放在html結構的不同位置。
原理:
當樣式表晚于結構性html加載,當加載到此樣式表時,頁面將停止之前的渲染。此樣式表被下載和解析后,將重新渲染頁面,也就出現了短暫的花屏現象。
解決方法:
使用LINK標簽將樣式表放在文檔HEAD中。
CSS 和 JS 放置順序, 異步機制
- 使用 link 標簽將樣式表放在頂部
- 將JS放在底部
- 腳本會阻塞后面內容的呈現
- 腳本會阻塞其后組件的下載
對于圖片和CSS, 在加載時會并發加載(如一個域名下同時加載兩個文件). 但在加載 JavaScript 時,會禁用并發,并且阻止其他內容的下載. 所以把 JavaScript 放入頁面頂部也會導致 白屏
現象.
白屏
上圖我們可以看到對于chrome瀏覽器來說,等所有的css加載完成并解析完成,
CSSOM
計算完成,把頁面你全部展示出來,所以會出現解析時間的白屏FOUC
上圖我們可以看到開始時字體比較小都是html的正常字體大小,然后當css加載完成后會出現加載css央視后的字體,頁面發生了變化,這是firefox的處理機制(無樣式內容閃爍)