通讀 HTML Standard

前言

只有掌握了 N-1 層的原理,才能精通第 N 層的抽象
                                   -- 佚名
複製代碼

視工做類型而定,有時候想掌握 N-1 層的原理,可能還須要瞭解 N-2,N-3 ...javascript

於前端程序員而言,第 N 層的抽象即 HTML/CSS/JS 語法,N+1 層是各類前端框架,N-1 層是語法的內部實現和瀏覽器的工做原理,N-2 層可能就是渲染引擎,JS 引擎,JS Runtime的實現。html

你見過沒有掌握 HTML/CSS/JS 卻精通 React 框架的人麼?前端

本文只談 HTML ,要想真正的精通 HTML ,咱們須要知道 HTML 的內部實現,通讀 HTML 規範是最有效的方法之一html5

經過本文,咱們想要達到的目的有:java

  1. 瞭解 Web 平臺的技術體系以及如何查找相關規範
  2. 瞭解 HTML 規範的總體結構,往後碰到疑難雜症能夠快速排查緣由

PS: 本文描述中的 「標準」 和 「規範」 指的是同一東西程序員

PS2: 爲何要看 HTML 規範?一般 API 文檔只告訴了咱們要這麼作,卻沒告訴咱們爲何不能這樣作,經過看規範,咱們能對 API 理解更加深入web

查找規範

首先明確一點, MDN 不是規範文檔,確切的說法是指南和開發教程,是對規範的二次解讀。 相比規範,MDN 在行文格式和專業術語的運用上更容易讓前端開發者接受。大部分狀況下,MDN 已可以解決問題。當發現 MDN 上的解釋不夠清晰時,這時候就能夠去看規範了。通常這種狀況,都是比較深刻底層的問題,畢竟,規範是用來給瀏覽器開發者看的。算法

Web 平臺的瀏覽器相關技術衆多,由不一樣的組織來肯定規範。 早在以前,關於 HTML 和 DOM 標準, W3CWHATWG 都有各類的規範,這嚴重阻礙了 HTML 的發展。chrome

W3C 但願發佈一個 finished 版本的 HTML5,而 WHATWG 想要不斷維護該規範而不是將已知問題凍結在某個版本canvas

不過現在兩個組織已達成一致,HTML 和 DOM 標準由 WHATWG 維護。

關於一項技術,如何肯定對應的規範並找到規範文檔,這裏推薦一個網站:The Web platform: Browser technologies 。 其列舉了 Web 平臺的瀏覽器相關技術的標準文檔和協議規範地址,包括如下幾大模塊:

  1. HTML,DOM,ECMAScript等核心模塊
  2. CSS
  3. Canvas,SVG 等圖形模塊
  4. 多媒體
  5. 平臺交互,事件及消息傳遞
  6. 文件和存儲
  7. 實時通訊模塊
  8. Web Components
  9. HTML 額外收錄模塊,如 Drag and drop
  10. 性能優化與分析
  11. 安全和隱私
  12. 其餘核心平臺額外收錄模塊,如 Mutation observers
  13. HTTP,Cookies 等基礎模塊
  14. 各類其餘的...

The Web Platform Browser technologies.png

頁面上用圖標指出了各個技術規範的制定組織,以及在 caniuse 和 MDN 中的地址,同時給出了該項技術的使用建議--理解使用/謹慎使用

細心的同窗能夠發現,WebSocket API 等技術和 HTML 都是定義在同一規範文檔 html.spec.whatwg.org/multipage/ 中,這個後文會說緣由

當咱們談到 HTML 規範的時候,咱們在說什麼?

咱們知道 html 是一種超文本標記語言,因此 HTML 規範指的是 html(包括文檔,元素和語法) 的編碼規範?

不是, HTML 規範 != HTML 編碼規範 。HTML 規範是對包括 html 語言在內的多種技術的規範定義,是瀏覽器開發者必須遵循的標準,並提供上層接口供頁面開發者使用。

HTML 規範是什麼

The HTML Standard is a kitchen sink full of technologies for the web. It includes the core markup language for the web, HTML, as well as numerous APIs like Web Sockets, Web Workers, localStorage, etc.

HTML 規範是多種 Web 技術的集合。它包括用於 Web 的核心標記語言 HTML 以及 Web Sockets, Web Workers, localStorage 等衆多API。相對於其餘規範,它在 Web 平臺的技術規範中的位置總結以下:

什麼是 HTML5 ?

狹義上來講, HTML5 定義 HTML 標準的最新的版本,所以本文也能夠說是 HTML5 標準

廣義上來講, HTML5 泛指現代 Web 技術,包括本文所定義的標準外,還有其餘如 Notifications API, WebRTC 等等

相關的還有 h5 這個名詞,在國內偏向於指代移動端的 web 頁面的解決方案

總體結構

本節介紹 HTML 規範的總體結構。

對於每一小節,會先介紹主體內容,而後列出相關技術點方便之後查找,可能還會給出注意事項

先上目錄:

  1. 概述
  2. 通用基礎結構
  3. HTML 文檔的語義、結構及API
  4. HTML 元素
  5. Microdata
  6. 用戶交互
  7. 頁面加載
  8. Web 應用 API
  9. 通訊
  10. Web workers
  11. Web 存儲
  12. HTML 語法
  13. XML 語法
  14. 渲染
  15. 廢棄的特性
  16. IANA 注意事項

須要重點看的有:7,8

1. 概述

介紹本規範的結構,提供閱讀說明及排版。

簡單介紹了跨站通訊和html的編寫以及常見的語法錯誤

提供了用於發現 HTML 錯誤的工具 -- HTML Conformance Checkers

2. 通用基礎結構

提供了術語說明和依賴的定義

規則中依賴的其餘規範的定義都會在本節作個概要描述

case-sensitive 表示區分大小寫的字符串比較

定義了策略控制功能,如 autoplay, document-domain

定義了常見的 microsyntaxes ,一些語法類型的問題能夠看這裏

HTML 中有不少地方接受特定的數據類型,如日期和數字,本節描述了對應類型內容應符合的標準,以及如何解析

定義了 URL ,描述瞭解析過程,以及 base URLs 變更後的效果

僅表層介紹,具體的須要調整至 URL 規範中查看

定義了資源獲取,包括同/跨域類型定義,資源類型肯定,meta 元素字符編碼提取過程,CORS 設置屬性,referrer 屬性,nonce 屬性

定義了通用 DOM 接口,包括 IDL 屬性獲取和設置,HTMLCollection 等集合接口,DOMStringList 接口,Document 的垃圾回收

定義告終構化數據,包括可序列化對象和可傳輸對象等

這一小節屬於比較底層了

3. HTML 文檔的語義、結構及API

介紹了 HTML 文檔的生命週期,一個 HTML 文檔表現爲一個 Document 對象,其上有各類屬性如元數據管理,DOM 樹訪問器,動態標記插入,用戶交互及 onreadystatechange

關於 Document, HTML 標準在 DOM 標準之上進行了拓展

enum DocumentReadyState { "loading", "interactive", "complete" };
typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;

[OverrideBuiltins]
partial interface Document {
  // resource metadata management 資源元數據管理
  [PutForwards=href, Unforgeable] readonly attribute Location? location;
  attribute USVString domain;
  readonly attribute USVString referrer;
  attribute USVString cookie;
  readonly attribute DOMString lastModified;
  readonly attribute DocumentReadyState readyState;

  // DOM tree accessors DOM 樹訪問器
  getter object (DOMString name);
  [CEReactions] attribute DOMString title;
  [CEReactions] attribute DOMString dir;
  [CEReactions] attribute HTMLElement? body;
  readonly attribute HTMLHeadElement? head;
  [SameObject] readonly attribute HTMLCollection images;
  [SameObject] readonly attribute HTMLCollection embeds;
  [SameObject] readonly attribute HTMLCollection plugins;
  [SameObject] readonly attribute HTMLCollection links;
  [SameObject] readonly attribute HTMLCollection forms;
  [SameObject] readonly attribute HTMLCollection scripts;
  NodeList getElementsByName(DOMString elementName);
  readonly attribute HTMLOrSVGScriptElement? currentScript; // classic scripts in a document tree only

  // dynamic markup insertion 動態標記插入
  [CEReactions] Document open(optional DOMString unused1, optional DOMString unused2); // both arguments are ignored
  WindowProxy? open(USVString url, DOMString name, DOMString features);
  [CEReactions] void close();
  [CEReactions] void write(DOMString... text);
  [CEReactions] void writeln(DOMString... text);

  // user interaction 用戶交互
  readonly attribute WindowProxy? defaultView;
  boolean hasFocus();
  [CEReactions] attribute DOMString designMode;
  [CEReactions] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional DOMString value = "");
  boolean queryCommandEnabled(DOMString commandId);
  boolean queryCommandIndeterm(DOMString commandId);
  boolean queryCommandState(DOMString commandId);
  boolean queryCommandSupported(DOMString commandId);
  DOMString queryCommandValue(DOMString commandId);

  // special event handler IDL attributes that only apply to Document objects
  // 只適用於 Document 對象的特殊事件處理器 IDL 屬性
  [LenientThis] attribute EventHandler onreadystatechange;

  // also has obsolete members
};
Document includes GlobalEventHandlers;
Document includes DocumentAndElementEventHandlers;
複製代碼

經過了解這個,咱們能更清楚的知道文檔的組成,對 document 屬性有疑問的均可以看本節

介紹了 HTML 元素,規則僅表示含義,不涉及呈現,所以各個瀏覽器呈現出來的特定元素效果可能不同。

HTML 元素的基本接口

[Exposed=Window]
interface HTMLElement : Element {
  [HTMLConstructor] constructor();

  // metadata attributes 元數據屬性
  [CEReactions] attribute DOMString title;
  [CEReactions] attribute DOMString lang;
  [CEReactions] attribute boolean translate;
  [CEReactions] attribute DOMString dir;

  // user interaction 用戶交互
  [CEReactions] attribute boolean hidden;
  void click();
  [CEReactions] attribute DOMString accessKey;
  readonly attribute DOMString accessKeyLabel;
  [CEReactions] attribute boolean draggable;
  [CEReactions] attribute boolean spellcheck;
  [CEReactions] attribute DOMString autocapitalize;

  [CEReactions] attribute [TreatNullAs=EmptyString] DOMString innerText;

  ElementInternals attachInternals();
};

HTMLElement includes GlobalEventHandlers;
HTMLElement includes DocumentAndElementEventHandlers;
HTMLElement includes ElementContentEditable;
HTMLElement includes HTMLOrSVGElement;

[Exposed=Window]
interface HTMLUnknownElement : HTMLElement {
  // Note: intentionally no [HTMLConstructor]
  // 注意:有意沒有 [HTMLConstructor]
};
複製代碼

介紹了 HTML 命名空間中名稱爲 name 的元素的元素接口的確認規則

舉例: xmp 元素原型是什麼? 答案是 HTMLPreElement (繼承自 HTMLElement )

介紹了元素構造器用於實現自定義元素

定義了內容模型,即每一個 HTML 元素的內容(其 DOM 中的子節點)必須符合內容模型的要求

舉例 <p><object><param><ins><map><a href="/">Apples</a></map></ins></object></p>
爲了檢查 a 元素中是否容許 "Apples",要檢查內容模型。 a 元素的內容模型是透明的,map 元素也是, ins 元素也是,object 元素中 ins 元素所在的部分也是。 object 元素位於 p 元素中,後者的內容模型是 短語內容。 所以 "Apples" 是容許的,由於文本是短語內容。

介紹了通用屬性,全部 HTML 元素均可以使用,如 contenteditable,style,title,dir,lang

介紹了 innerText 的執行步驟

4. HTML 元素

每一個元素都有一個預約義的含義,本章便解釋了這些含義。 也給出了做者使用這些元素的規則,以及用戶代理處理這些元素的要求。 這裏包含了大量的 HTML 獨有的特性,例如視頻播放和副標題,表單控件和表單提交, 以及名爲 HTML canvas 的 2D 圖形 API。

有具體元素使用上的疑問能夠在本章中查找

5. Microdata

本標準介紹了爲文檔增長機器可讀註解的機制,這樣工具能夠從文檔中抽取鍵值對的樹。 這部分文檔描述了該機制和用於將 HTML 文檔轉換爲其餘格式的一些算法。 這部分還爲聯繫信息、日曆事件和許可協議定義了一些示例的微數據詞彙。

itemscope 上的使用有疑問,先看 MDN 再看本章

6. 用戶交互

HTML Document 能夠提供一些用戶與內容交互以及用戶修改內容的機制,在本章中給出了這些機制的描述。

提供了 hidden 屬性的描述

display: block 能夠覆蓋 hidden 的效果

描述了惰性子樹的概念

舉個常見的例子,在A元素中 mouseDown 而後移動到 B 元素上並 mouseUp ,mouseMove 和 click 事件是在A元素上觸發,B 是惰性的

描述了焦點的工做機制

這裏的處理挺複雜的

描述了用於激活元素的指定快捷鍵 -- accesskey

描述了可編輯元素的相關接口和 API:contenteditable, designMode, execCommand, inputmode

描述了元素拖拽的相關接口和處理過程,其中部分章節是非規範的,因此瀏覽器間的實現會有差別

7. 頁面加載

這部分定義了不少影響處理多頁面環境的特性。要深刻理解瀏覽器的運行過程,本章節須要細讀。

描述了瀏覽上下文的定義和分類,包括嵌套瀏覽上下文(iframe)和輔助瀏覽上下文(window.opener)

描述了 Window, WindowProxy, 和 Location 對象的安全基礎設施

這裏介紹了 window.open 等方法的執行機制

介紹了 Origin 的定義和同源判斷算法,以及 document.domain 賦值描述

介紹了沙盒機制(sandboxing)

介紹了會話歷史和導航接口: history 和 location

描述了瀏覽上下文導航和頁面加載處理模型

描述了離線應用緩存。

8. Web 應用 API

這部分介紹了 HTML 應用腳本的基本特性。也是須要重點細讀的章節

介紹了腳本,包括 javascript: URL ,啓用禁用腳本,腳本處理模型,Event Loops 和瀏覽器事件

Event Loops 一節還講述了和渲染引擎的交互

介紹了 WindowOrWorkerGlobalScope mixin,描述了全局對象上公開的 API

typedef (DOMString or Function) TimerHandler;

interface mixin WindowOrWorkerGlobalScope {
  [Replaceable] readonly attribute USVString origin;

  // base64 工具方法
  DOMString btoa(DOMString data);
  ByteString atob(DOMString data);

  // timers
  long setTimeout(TimerHandler handler, optional long timeout = 0, any... arguments);
  void clearTimeout(optional long handle = 0);
  long setInterval(TimerHandler handler, optional long timeout = 0, any... arguments);
  void clearInterval(optional long handle = 0);
  
  // microtask queuing
  void queueMicrotask(VoidFunction callback);

  // ImageBitmap
  Promise<ImageBitmap> createImageBitmap(ImageBitmapSource image, optional ImageBitmapOptions options);
  Promise<ImageBitmap> createImageBitmap(ImageBitmapSource image, long sx, long sy, long sw, long sh, optional ImageBitmapOptions options);
};
Window includes WindowOrWorkerGlobalScope;
WorkerGlobalScope includes WindowOrWorkerGlobalScope;
複製代碼

其中介紹了 Base64 工具方法 , Timers 執行過程,microtask 和 ImageBitmap 處理

介紹了動態標記插入

萬惡的 document.write

介紹了用戶提示窗口方法: alert,confirm,prompt 的內部處理和 print 打印機提示方法

能夠了解這些方法執行時再事件循環中的處理是怎樣的

介紹了系統狀態和功能 Navigator ,描述了基本功能接口和自定義方案處理程序

所以瀏覽器能夠經過自定義方案處理程序拓展功能,如 geo , gamepads

最後介紹了動畫幀,定義了 requestAnimationFrame 和 cancelAnimationFrame

9. 通訊 API

這部分描述了 HTML 編寫的應用可用來與同一客戶端中的,不一樣域名的其餘應用通訊的一些機制。 也介紹了一個服務器推送事件流機制,稱爲 Server Sent Events 或 EventSource, 以及一個爲腳本提供的雙向全雙工套接字協議,稱爲 Web Sockets。

首先介紹了繼承自 Event 的 MessageEvent 接口,本章介紹的事件消息都是基於 MessageEvent 接口

介紹了服務器發送的事件,引入了 EventSource 接口定義和實現

介紹了 Web sockets 的組成和內部處理

引入了 postMessage 跨文檔通訊,用來解決非同源文檔間通訊問題,且不會形成跨站腳本攻擊

介紹了 MessageChannel 通道用來實現不一樣瀏覽上下文之間代碼通訊

最後介紹了向其餘瀏覽上下文廣播的方案 BroadcastChannel

10. Web workers

這部分定義了 JavaScript 後臺線程的 API。

描述了一些使用場景,如數字密集型計算,共享 worker

描述了做用域和事件循環

描述了可用的 API

11. Web storage

這部分定義了一個基於鍵值對的客戶端存儲機制。

定義了咱們經常使用的 API: localStorage 和 sessionStorage 以及 storage 事件

二者的區別是 sessionStorage 在瀏覽器關閉後內容會消失

描述了 storage 的可用磁盤空間,不過標準沒有給出具體值,只是建議每一個域 5M 的限制(未壓縮前)

描述了 storage 的隱私和安全問題

12. HTML 語法

本章描述有 HTML MIME type 標註的資源的語法規則

介紹了文檔的組成部分,包括 DOCTYPE 和 Elements 類型。描述了標籤和屬性的解析規則

描述了 HTML 文檔解析的處理模型,包括錯誤處理,輸入字節流,解析狀態,Tokenization 和樹結構等

從圖中也可看出 html 解析和腳本執行的關係

腳本執行會阻塞 DOM 的解析,試想下,不阻塞的話,腳本中修改了 DOM 那還得調整原來構建的 DOM 樹

描述了 HTML 片斷的序列化和解析

13. XML 語法

本章描述 XML 資源的語法規則,主要是描述 XML 文檔的解析,以及 XML 片斷的序列化和解析

14. 渲染

這部分定義了 Web 瀏覽器默認的渲染規則。

注意,本章僅是建議,沒有要求瀏覽器必須這樣實現

所以,各類渲染引擎的效果不同是按規範來

本章更多的是講元素的預期渲染效果,渲染引擎機制請看 Event Loops 一節

15. 廢棄的特性

包括三部分

  1. 過期但仍可用的特徵,如在 img 上指定 border 屬性
  2. 不可用的特徵,如使用 applet 元素(應該用 embed 代替)
  3. 一些元素,API 應該實現的接口

這部份內容比較針對瀏覽器開發者

16. IANA considerations

本章主要描述使用資源類型和協議時的一些注意事項

問題記錄

Q1. 頁面跳轉和導航的代碼執行問題

下面代碼分別輸出什麼,爲何?請從瀏覽上下文和事件循環等角度分析。

function onClick1(){
  window.open('https://www.baidu.com')
  console.log("onClick1")
}
function onClick21(){
  location.href = "https://www.baidu.com"
  console.log("onClick21")
}
function onClick22(){
  location.href = "https://www.baidu.com"
  // 3s
  let start = +new Date
  while(+new Date - start< 3*1000){}
  console.log("onClick22")
}
function onClick23(){
  // 未能加載成功的網站
  location.href = "https://sssss"
  // 3s
  let start = +new Date
  while(+new Date - start< 3*1000){}
  console.log("onClick23")
}
function onClick3(){
  history.back()
  // 3s
  let start = +new Date
  while(+new Date - start< 3*1000){}
  console.log("onClick3")
}
複製代碼
Answer

onClick21 onClick23 onClick3 會輸出

僅以 chrome 的實現爲例,每一個標籤頁都是獨立的用戶代理(user agent)

首先,頁面 A 存在着(至少)一個瀏覽上下文,並對應着一個 Event Loop

考慮嵌套瀏覽上下文和輔助瀏覽上下文,因此這邊用的是至少

頁面 A 中執行了某段同步代碼(一個Task),在其中調用了 window.open 方法,該方法是當即執行的

內部作了不少處理,能夠點連接看看

執行完畢 ,此時會建立一個新的瀏覽上下文以及對應的 Event Loop

若是 頁面 A 採用 opener 參數打開的頁面 B,則頁面 B 還有一個輔助瀏覽上下文,指向頁面 A 的瀏覽上下文,共用同一個 Event loop??

若是要加載的文檔是 html ,頁面 B 的用戶代理會排一個 Task 建立 Document 對象,標記爲 HTML 文檔,其後讀取和解析文檔。

location 跳轉

location 是同步執行的,後臺線程等解析完文檔就會跳轉,不會等後面的同步代碼。一般咱們後面的同步代碼很快執行,因此會誤覺得 location 是異步執行的

詳見 stackoverflow設置location.href,爲何不會當即跳轉? - 知乎

PS: 還沒詳細看規範,不知道是否是這樣處理

history 跳轉是一個 Task,所以它會在本次同步代碼執行完畢後才執行

這個看運行時環境實現,可能其餘任務還會先與該 Task 前執行

總結: window.openlocation.href 不屬於 Web API 的範疇,也就不走 event loop 那一套

未完待續...

相關文章
相關標籤/搜索