網頁中嵌入 JavaScript 程式碼,主要有三種方法。
-
<script>
元素直接嵌入程式碼。 -
<script>
標籤載入外部指令碼 -
事件屬性
-
URL 協議
script 元素
工作原理
- 瀏覽器一邊下載
HTML
網頁,一邊開始解析。也就是說,不等到下載完,就開始解析。 - 解析過程中,瀏覽器發現
<script>
元素,就暫停解析,把網頁渲染的控制權轉交給JavaScript
引擎。 - 如果
<script>
元素引用了外部指令碼,就下載該指令碼再執行,否則就直接執行程式碼。 JavaScript
引擎執行完畢,控制權交還渲染引擎,恢復往下解析HTML
網頁。
defer屬性
他的作用是延遲指令碼執行,等到 DOM 載入生成後,在執行指令碼。
defer
屬性的執行流程如下。
- 瀏覽器開始解析 HTML 網頁。
- 解析過程中,發現帶有defer屬性的
<script>
元素。 - 瀏覽器繼續往下解析 HTML 網頁,同時並行下載
<script>
元素載入的外部指令碼。 - 瀏覽器完成解析 HTML 網頁,此時再回過頭執行已經下載完成的指令碼。
async屬性
解決“阻塞效應”的另一個方法是對<script>
元素加入async
屬性。
async
屬性的作用是,使用另一個程式下載指令碼,下載時不會阻塞渲染。
- 瀏覽器開始解析 HTML 網頁
- 解析過程中,發現帶有
async
屬性的script
標籤 - 瀏覽器繼續往下解析 HTML 網頁,同時並行下載
<script>
標籤中的外部指令碼。 - 指令碼下載完成,瀏覽器停止解析 HTML 網頁,開始執行下載的指令碼
- 指令碼執行完畢,瀏覽器恢復解析 HTML 網頁
async
屬性可以保證指令碼下載的同時,瀏覽器繼續渲染。需要注意的是,一旦採用這個屬性,就無法保證指令碼的執行順序。哪個指令碼先下載結束,就先執行那個指令碼。另外,使用async
屬性的指令碼檔案裡面的程式碼,不應該使用document.write
方法。
指令碼載入使用的協議
如果不指定協議,瀏覽器預設採用 HTTP
協議下載。
<script src="example.js"></script>
複製程式碼
上面的example.js
預設就是採用 HTTP 協議下載,如果要採用 HTTPS 協議下載,必需寫明。
<script src="https://example.js"></script>
複製程式碼
但是有時我們會希望,根據頁面本身的協議來決定載入協議,這時可以採用下面的寫法。
<script src="//example.js"></script>
複製程式碼
瀏覽器的組成
瀏覽器的核心是兩部分:渲染引擎和JavaScript引擎
渲染引擎的主要作用是將網頁程式碼渲染為使用者視覺可以感知的平明文件。處理網頁分為四個階段:
- 解析程式碼:HTML 程式碼解析為 DOM , CSS程式碼解析為 CSSOM
- 物件合成:將 DOM 和 CSSOM 合成一個渲染樹
- 佈局:計算渲染樹的佈局
- 繪製:將渲染樹繪製到螢幕
重流和重繪
渲染樹轉換為網頁佈局,稱為“佈局流”;佈局顯示到頁面的過程稱為“繪製”。
頁面生成以後,指令碼操作和樣式表操作,都會觸發“重流”和“重繪”。
重流和重繪並不一定一起發生,重流必然導致重繪,重繪不一定需要重流。
優化技巧:
-
讀取 DOM 或者寫入 DOM,儘量寫在一起,不要混雜。不要讀取一個 DOM 節點,然後立刻寫入,接著再讀取一個 DOM 節點。
-
快取 DOM 資訊。
-
不要一項一項地改變樣式,而是使用 CSS class 一次性改變樣式。
-
使用
documentFragment
操作 DOM ``動畫使用absolute
定位或fixed
定位,這樣可以減少對其他元素的影響。 -
只在必要時才顯示隱藏元素。
-
使用
window.requestAnimationFrame()
,因為它可以把程式碼推遲到下一次重流時執行,而不是立即要求頁面重流。 -
使用虛擬 DOM(virtual DOM)庫。
// 重繪代價高
function doubleHeight(element) {
var currentHeight = element.clientHeight;
element.style.height = (currentHeight * 2) + 'px';
}
all_my_elements.forEach(doubleHeight);
// 重繪代價低
function doubleHeight(element) {
var currentHeight = element.clientHeight;
window.requestAnimationFrame(function () {
element.style.height = (currentHeight * 2) + 'px';
});
}
all_my_elements.forEach(doubleHeight);
複製程式碼
avaScript 引擎的主要作用是,讀取網頁中的 JavaScript 程式碼,對其處理後執行。