忍者 Chapter2. 在執行時期產生網頁
Web應用程式生命週期
❗️ javascript如何適應這個生命週期
- 瀏覽器能否用遠正確地根據HTML代碼產生出網頁?
- 一個Web應用程式可以同時處理多少事件?
- 為什麼瀏覽器必須使用事件佇列來處理多的事件?
生命週期概述
由頁面建立和事件處理兩的階段組成
- 開始於使用者輸入URL連結或點擊URL連結
- 瀏覽器發聲請求傳送到伺服器
- 伺服器處理請求並產生由HTML, CSS, JavaScript所組成的回應頁面
- 瀏覽器接收到這個回應頁面,便是Web應用程式開始有生命的一刻
- 事件處理,進入一個等待事件發生的迴圈 (6)
- 使用者與頁面元素互動(5)
- 使用者關閉頁面,網頁的生命週期結束
頁面建立階段
透過
- 解析HTML並建立文件物件模型(DOM)
- 執行Javascript程式
瀏覽器根據需要,在這兩個步驟切換許多次
解析HTML並建立DOM
- 一次處理一個HTML元素
- 一個節點可以有任何數量的子結點
- 相同父元素的子節點稱為兄弟元素
- 遇到特殊類型的HTML元素(如script),瀏覽器會值時停止由HTML代碼來建立DOM,而開始執行JavaScript
DOM由HTML所建構,但兩者不相同。
HTML為建立最初的DOM所遵循的藍圖,瀏覽器會修復在藍圖中發現的問題並建立有效的DOM
執行JAVAScript程式碼
script中所有的JavaScript由瀏覽器的JavaScipt引擎執行
瀏覽器 | JavaScript引擎 |
---|---|
Firefox | Spidermonkey |
Chrome、Opera | V8 |
Edge、IE | Chakra |
JS程式碼的主要目的為提供頁面的行為,瀏覽器藉由一個全域物件提供一組API,讓JS引擎與頁面互動並修改頁面
JavaScript中的全域物件
瀏覽器給JS引擎的主要全域物件是window物件,代表頁面所屬的瀏覽器視窗。
window是一個特殊的全域物件,可以透過它還存取所有其他的全域物件、全域變數及瀏覽器API。
window最重要的屬性是document
,也就是目前頁面的DOM結構
JS可以任意改變頁面上的DOM結構。
1 | var first = document.getElementById('first') |
使用document
全域物件從DOM結構找出ID為first
的元素
不同類型的JavaScript
分為全域程式(Global code) 及 函式程式(function code)
兩者主要的區別是它們所在的位置。
1 | <script> |
全域程式會被JS引擎自動的逐行直接執行。
函式程式的執行必須由其他程式如全域程式、其他函式或由瀏覽器呼叫。
在頁面建立階段執行JavaScript程式碼
瀏覽器在頁面建立階段遇到script
節點時會暫停使用HTML代碼來建立DOM結構,並開始執行JS程式碼。
JS可以任意的修改DOM結構:建立新節點、修改或刪除現有節點,但不能修改尚未建立的元素
人們傾向把script放在頁面底部的原因之一,不必擔心特定的HTML元素有沒有被讀到
當執行完script中的最後一行code,瀏覽器並離開JS執行模式,並繼續處理HTML代碼來建立其他的DOM節點,並反覆的上述行為。
此時已執行過的script元素中,由使用者定義的全域變數能繼續被其他的script中元素的JS所存取ㄝ,因為存放了所有全域變數的window的全域物件,在頁面的整個生命週期內都是有效且可以存取的。
當瀏覽器處理完所有的HTML元素,頁面建立階段完成,並進入生命週期第二部分事件處理
事件處理
在頁面建立階段,JS除了影響全域狀態及修改DOM結構外,還可以註冊事件監聽器(處理器),即在事件發生時要執行的函式。
事件處理概述
瀏覽器執行環境的核心為一次執行一段程式碼,為了避免大量阻塞,瀏覽器需要一種方法來追蹤已發生但尚未處理的事件
所有已發生事件都會按照順序放置在同一個事件佇列中,交由瀏覽器檢測。
- 瀏覽器檢查事件佇列的頂部
- 如果沒有事件,瀏覽器會持續檢查
- 如果有一事件,瀏覽器會存取他,並執行處理程式。執行期間,剩餘待處理事件間耐心等待直到被處理
避免編寫需要大量執行時間的事件處理程式,會導致WEB無法產生回應
將事件放入事件佇列的瀏覽器工作機制,是在頁面建立和事件處理階段之外。判斷事件何時發生,並放入事件佇列的這些動作並不在處理事件的執行緒中
事件是非同步的
無法預測事件的發生的順序,因此事件的處理、對事件處理的函式呼叫是非同步的。
可能會發生的事件
- 瀏覽器事件,如頁面處於以載入會未載入的狀態
- 網路事件,如來自伺服器的回應Ajax事件、伺服器端事件)
- 使用者事件,如點擊滑鼠、移動滑鼠、按下鍵盤
- 計時器事件,如等候逾時或間隔性的觸發條件
程式碼是在事前完成設置,以便在之後執行。
除了全域程式,在頁面上大多的程式都是某些事件的結果而被執行。
註冊事件處置器
Event-handler registration, 事件處置器是在特定的事件時發生執行的函式。
有兩種註冊事件方式:
- 將函式指定給特殊屬性
- 使用內建的addEventListener方法
1 | window.onload = function(){}; |
不建議使用以上方式,缺點是某一特定事件只能指派一個事件處理器,很容易蓋掉之前的事件處理函式。
一個好的替代方式addEventListener
1 | <script> |
處理事件
事件處理的主要概念適當事件發生時,瀏覽器呼叫相關的事件處理器。
模擬情境
- 當頁面建置完成使用者開始移動滑鼠即點擊滑鼠
- 瀏覽器依順序加入將mousemove和click事件放置到事件佇列上
- 事件處理階段:佇列頂端有一個mousemove事件,並執行相關事件處理器,此時click事件等待中
- mousemove最後一行執行完畢,並且JS引擎退出該事件函式,mousemove事件處理完成
- 事件迴圈再次檢查佇列,找到click事件並執行
- (重複動作直到使用者關閉Web)
總結
- 瀏覽器接收HTML代碼作為建立DOM結構的藍圖,而DOM就是客戶端WEB的的結構表現
- 我們透過Javascript程式動態的修改DOM結構,以便為WEB展現動態行為
- 客戶端的WEB執行分為兩個階段:
- 頁面建立:處理HTML以建立DOM結構,遇到
<script>
執行全域程式,執行時可修改DOM結構,及註冊事件處理器(addEventListener) - 事件處理:按照事件產生的順序逐一執行,仰賴事件佇列,事件按照他們的發生的順序被儲存起來。事件回圈會一直檢查事件佇列是否有事件,如果有,呼叫執行函式
- 頁面建立:處理HTML以建立DOM結構,遇到
名詞解釋
- DOM(Document Object Model)文件物件模型:
客戶端Web使用者介面的結構化表示,只少一開始,他是由Web中的HTML代碼所構成 - 事件:
絕大多數的JS代碼都是事件驅動的應用程式,意味著程式碼都是為了回應特定事件而執行,事件包含網路事件、計時器、使用者事件 - 瀏覽器API:
瀏覽器提供了一組API,允許我們存取設備資訊、在本地端存取資料或與遠端伺服器通訊