按图索骥系列之—— DOM 里面有什么?

786 阅读4分钟

DOM (Document Object Model) 这个大名鼎鼎的东西,是什么?究竟在 HTML 之中扮演着什么样的地位?今天我们来一探究竟。

1. DOM

在 HTML 用户代理工具(通常指浏览器)中,每个 XML 和 HTML 文档都有与之对应文档对象,俗称 Document Object。我们常常提到的 DOM 也就是文档对象模型。通过一系列规范来约定了不同的用户代理工具应该实现什么样的标准。当然,由于互联网的快速发展。浏览器厂商往往先行于标准出现,规范的制定在早期的 web 发展中略有些后知后觉,进而导致兼容性的问题层出不穷。后来又到了 jQuery 统一包装的兼容性问题而大行其道,这是后话。

DOM 规范定义了 文档对象的 URL。它在文档对象被创建的时候就建立了,但是在文档对象的生命周期中可以改变。而改变 DOM 的 URL,需要借助浏览器对象模型的 API。即:BOM 的 window.history.pushState 方法。需要注意的是,浏览器通常会暴露出当前 DOM 的 URL,也就是浏览器一般都具备地址栏。这么做的目的是为了让用户来区分该网站是不是被假冒的。

DOM 对象都有一个重载覆写标记,这个标记最开始没有被设置。当 document.open()document.write() 在某些情况下被调用时,才被设置。这个标记在 DOM 中用于文档源码,该标记会使用由 Unicode 编码字符的重载覆写缓存来载入文档。

2. DOM 接口

下图是 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
  getter object (DOMString name);
  [CEReactions] attribute DOMString title;
  attribute DOMString dir;
  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
  Document open(optional DOMString type = "text/html", optional DOMString replace = "");
  WindowProxy open(DOMString url, DOMString name, DOMString features, optional boolean replace = false);
  [CEReactions] void close();
  [CEReactions] void write(DOMString... text);
  [CEReactions] void writeln(DOMString... text);

  // user interaction
  readonly attribute WindowProxy? defaultView;
  readonly attribute Element? activeElement;
  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
  [LenientThis] attribute EventHandler onreadystatechange;
};
Document implements GlobalEventHandlers;
Document implements DocumentAndElementEventHandlers;

上面的定义中我们可以找到一些很熟悉的方法定义如:NodeList getElementsByName(DOMString elementName);。这些内容规范了 DOM 应该具备的基本接口和数据类型。如果了解过 jQuery 源码,应该对 document.readyState 也不陌生。这个状态正是用来判断文档加载状态的。

3. 元素

元素在 DOM 中是具备语义的,比如 ol 元素代表一个有序列表, img 代表一张图片等等。在 DOM 元素这个大集合中,主要有两部分组成:内容模型和全局属性。内容模型主要根据不同类型的标签做出分类比如 嵌入式内容 里面主要由 audio canvas embed iframe img math object picture svg video 这些标签组成。这些标签有个显著的特点是它们都含有自己特有的内容,这一点从语义上也能辨别。

还有一些标签称为“透明内容模块”。比如注音标签。不是常用标签,但很有特点。

元素的全局属性我们并不陌生。最常见的莫过于 title 标记。常常用于鼠标移入的浮动提示信息展示。还有一个 dir 标签用于排列文字方向,注意这个与 text-align 的对齐方向是不同的概念。

提及元素及其语义,可访问性是个绕不开的话题。W3C 关于无障碍阅读,也就是可访问性这是个极具探讨性的话题。我们在这里不会展开篇幅来说。关于网页的无障碍阅读,主要涉及到颜色对比度设置,放大操作,键鼠响应等一系列优化,还有利于其他阅读器识别的语义,比如朗读标记等。无障碍阅读也能狭义的理解为,一张网页,既能在浏览器中供正常人浏览,也能在各种残障人士的阅读设备中浏览。这是一种人文关怀在技术上的衍生,虽然目前的实践还不够完善。但既然有标准,就值得去探索。

DOM API 简介到这里为止。下一次,我们将着眼于 HTML 元素,这是里用户最近的内容。比较常见的表单元素,脚本元素,分组元素,以及各种链接元素和编辑元素都将一一出现。

pic