《JavaScript高級(jí)程序設(shè)計(jì)》Chapter 12 DOM 2 和 DOM 3

DOM 變化

  1. 如何確認(rèn)瀏覽器是否支持 DOM 2 和 DOM 3 新增的模塊:

    var supportsDOM2Core = document.implementation.hasFeature('Core', '2.0')
    var supportsDOM3Core = document.implementation.hasFeature('Core', '3.0')
    var supportsDOM2HTML = document.implementation.hasFeature('HTML', '2.0')
    var supportsDOM2Views = document.implementation.hasFeature('Views', '2.0')
    var supportsDOM2XML = document.implementation.hasFeature('XML', '2.0')
    
  2. 針對(duì) XML 命名空間的變化

    • 混合命名空間

      <html xmlns="http://www.w3.org/1999/xhtml">
          <head>
              <title> Example XHTML page </title>
          </head>
          <body>
              <svg xmlns="http://www/w3.org/2000/svg" version="1.1" viewBox="0 0 100 100" style="width: 100%; height: 100%">
                  <rect x="0" y="0" width="100" height="100" style="fill: red" />
              </svg>
          </body>
      </html>
      
    • 在 DOM 2 中,Node 類型包含下列特定于命名空間的屬性:

      • localName:不帶命名空間前綴的節(jié)點(diǎn)名稱
      • namespaceURI:命名空間 URI 或者(在未指定的情況下)null
      • prefix:命名空間前綴或者(在未指定的情況下)null
    • DOM 3 引入了下列與命名空間有關(guān)的方法:

      • isDefaultNamespace(namespaceURI):在指定的 namespaceURI是當(dāng)前節(jié)點(diǎn)的默認(rèn)命名空間時(shí)返回 true
      • lookupNamespaceURI(prefix):返回給定 prefix 的命名空間。
      • lookupPrefix(namespaceURI):返回給定 namespace 的前綴。
    • DOM 2 的 Document 也發(fā)生了變化基括,包含了下列與命名空間有關(guān)的方法:

      • createElementNS(namespaceURI, tagName):使用給定的 tagName 創(chuàng)建一個(gè)屬于命名空間 namespace 的新元素乳蓄。
      • createAttributeNS(namespaceURI, attributeName):使用給定的 attributeName 創(chuàng)建一個(gè)屬于命名空間 namespaceURI 的新特性恬吕。
      • getElementsByTagNameNS(namespaceURI, tagName):返回屬于命名空間 namespaceURItagName 元素的 NodeList 故黑。
    • DOM 2 也為 Element 新增了一些方法:

      • getAttributeNS(namespaceURI, localName):取得屬于命名空間 namespaceURI 且名為 localName 的特性。
      • getAttributeNodeNS(namespaceURI, localName):取得屬于命名空間 namespaceURI 且名為 localName 的特性節(jié)點(diǎn)颁独。
      • getElementsByTagNameNS(namespaceURI, tagName):返回屬于命名空間 namespaceURItagName 元素的 NodeList
      • hasAttributeNS(namespaceURI, localName):確定當(dāng)前元素是否有一個(gè)名為 localName 的特性伪冰,而且該特性的命名空間是 namespaceURI 誓酒。
      • removeAttributeNS(namespaceURI, localName):刪除屬于命名空間 namespaceURI 且名為 localName 的特性。
      • setAttributeNS(namespaceURI, qualifiedName, value):設(shè)置屬于命名空間 namespaceURI 且名為 qualifiedName 的特性值為 value 贮聂。
      • setAttributeNodeNS(attNode):設(shè)置屬于命名空間 namespaceURI 的特性節(jié)點(diǎn)靠柑。
    • NamedNodeMap 類型也新增了下列與命名空間有關(guān)的方法。由于特性是通過(guò) NamedNodeMap 表示的吓懈,因此這些方法多數(shù)情況下只針對(duì)特性使用:

      • getNamedItemNS(namespaceURI, localName):取得屬于命名空間 namespaceURI 且名為 localName 的項(xiàng)歼冰。
      • removeNamedItemNS(namespaceURI, localName):移除屬于命名空間 namespaceURI 且名為 localName 的項(xiàng)。
      • setNamedItemNS(node)?:添加 node 耻警。這個(gè)節(jié)點(diǎn)已經(jīng)事先指定了命名空間信息隔嫡。
  3. 其他方面的變化

    • DocumentType 新增了三個(gè)屬性:
      • publicId:文檔類型聲明中的信息段之一(- //W3C//DTD HTML 4.0.1//EN
      • systemId:文檔類型聲明中的信息段之一(http://www.w3.org/TR/html4/strict.dtd
      • internalSubset:訪問(wèn)包含在文檔類型聲明中的額外定義。
    • Document 類型的變化:
      • 新增 importNode() 用來(lái)從一個(gè)文檔中獲取一個(gè)節(jié)點(diǎn)甘穿,然后將其導(dǎo)入到另一個(gè)文檔中腮恩,使其成為這個(gè)文檔結(jié)構(gòu)的一部分。

        • 每個(gè)節(jié)點(diǎn)都有一個(gè) ownerDocument 屬性扒磁,表示所屬的文檔庆揪。如果調(diào)用 appendChild() 時(shí)傳入的節(jié)點(diǎn)屬于不同的文檔,會(huì)導(dǎo)致錯(cuò)誤妨托。但是在調(diào)用 importNode() 的時(shí)候回返回一個(gè)歸當(dāng)前文檔所有的新的節(jié)點(diǎn)缸榛。
      • 新增 defaultView 屬性,保存一個(gè)指針兰伤,指向擁有給定文檔的窗口(或框架)内颗。IE 不支持這個(gè)屬性,但有一個(gè)等價(jià)的屬性名叫 parentWindow敦腔。因此均澳,要確定文檔窗口,可以使用以下代碼:

        var parentWindow = document.defaultView || document.parentWindow
        
      • DOM 2 Core 為 document.implementation 對(duì)象規(guī)定了兩個(gè)新方法:

        • createDocumentType():創(chuàng)建一個(gè)新的 DocumentType 節(jié)點(diǎn)。接收三個(gè)參數(shù):文檔類型名稱找前、publicId糟袁、systemId。這個(gè)方法只在創(chuàng)建新文檔時(shí)有用躺盛。

          var doctype = document.implementation.createDocumentType("html", "-//W3C//DTD HTML 4.01//EN", "http://www.w3.org/TR/html4/strict.dtd")
          
        • createDocument():創(chuàng)建新文檔项戴。接收三個(gè)參數(shù):接受文檔中元素的 namespaceURI、文檔元素的標(biāo)簽名槽惫、新文檔的文檔類型周叮。

          var doc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", doctype)
          
      • DOM 2 HTML 為 document.implementation 新增了一個(gè)方法:createHTMLDocument() 。這個(gè)方法的用途是創(chuàng)建一個(gè)完整的 HTML 文檔界斜,包括 html, head, title, body 元素仿耽。它只接受一個(gè)參數(shù),即新創(chuàng)建的文檔的標(biāo)題(放在 title 里)各薇,返回新的 HTML 文檔项贺。只有 Opera 和 Safari 支持這個(gè)方法

    • Node 類型的變化
      • 添加了 isSupported() 方法:用于確定當(dāng)前節(jié)點(diǎn)具有什么能力得糜。接收兩個(gè)參數(shù):特性名敬扛、特性版本號(hào)。如果瀏覽器實(shí)現(xiàn)了相應(yīng)特性朝抖,而且能夠基于給定節(jié)點(diǎn)執(zhí)行該特性啥箭,就返回 true

        document.body.isSupported("HTML", "2.0")
        
      • DOM 3 引入了兩個(gè)輔助比較節(jié)點(diǎn)的方法:

        • isSameNode():接收一個(gè)節(jié)點(diǎn)參數(shù)治宣,并在傳入節(jié)點(diǎn)與引用的節(jié)點(diǎn)相同(即同一個(gè)對(duì)象)時(shí)返回 true急侥。
        • isEqualNode():接收一個(gè)節(jié)點(diǎn)參數(shù),并在傳入節(jié)點(diǎn)與引用的節(jié)點(diǎn)相等(即類型相同)時(shí)返回 true
      • DOM 3 針對(duì)為 DOM 節(jié)點(diǎn)添加額外數(shù)據(jù)引入了新方法:

        • setUserData():將數(shù)據(jù)指定給節(jié)點(diǎn)侮邀。接收三個(gè)參數(shù):要設(shè)置的鍵坏怪、實(shí)際的數(shù)據(jù)(可以是任何數(shù)據(jù)類型)、處理函數(shù)绊茧。
        • getUserData():接收相同的三個(gè)參數(shù)铝宵,獲取數(shù)據(jù)。
        • 傳入 setUserData() 中的處理函數(shù)會(huì)在帶有數(shù)據(jù)的節(jié)點(diǎn)被復(fù)制华畏、刪除鹏秋、重命名或引入一個(gè)文檔時(shí)調(diào)用。處理函數(shù)接收五個(gè)參數(shù):表示操作類型的數(shù)值(1 - 復(fù)制亡笑,2 - 導(dǎo)入侣夷,3 - 刪除,4 - 重命名)仑乌,數(shù)據(jù)鍵百拓、數(shù)據(jù)值琴锭、源節(jié)點(diǎn)和目標(biāo)節(jié)點(diǎn)。刪除時(shí)源節(jié)點(diǎn)是 null 衙传;除復(fù)制外目標(biāo)節(jié)點(diǎn)是 null 决帖。
    • 框架的變化
      • HTMLFrameElement 和 HTMLIFrameElement 在 DOM 2 中都有了一個(gè)新屬性:contentDocument。它包含一個(gè)指針蓖捶,指向表示框架內(nèi)容的文檔對(duì)象古瓤。在此之前,無(wú)法直接通過(guò)元素取得這個(gè)文檔對(duì)象(只能使用 frames 集合)腺阳。
        • contentDocument 屬性是 Document 類型的實(shí)例,因此可以像使用其他 HTML 文檔一樣使用它穿香,包括所有屬性和方法亭引。IE 8 之前不支持這個(gè)屬性,但是支持一個(gè)名叫 contentWindow 的屬性皮获。

          var iframe = document.getElementById('myIframe')
          var iframeDoc = iframe.contentDocument || iframe.contentWindow.document
          

樣式

  1. 確定瀏覽器是否支持 DOM 2 級(jí)定義的 CSS 能力:

    var supportsDOM2CSS = document.implementation.hasFeature('CSS', '2.0')
    var supportsDOM2CSS2 = document.implementation.hasFeature('CSS2', '2.0')
    
  2. 訪問(wèn)元素的樣式:

    • 任何支持 style 特性的 HTML 元素在 JavaScript 中都有一個(gè)對(duì)應(yīng)的 style 屬性焙蚓。這個(gè) style 對(duì)象是 CSSStyleDeclaration 的實(shí)例,包含著通過(guò) HTML 的 style 特性指定的所有樣式信息洒宝,但不包含與外部樣式表或嵌入樣式表經(jīng)層疊而來(lái)的樣式购公。在 style 特性中指定的任何 CSS 屬性都將表現(xiàn)為這個(gè) style 對(duì)象的相應(yīng)屬性。對(duì)于使用短劃線的 CSS 屬性名雁歌,必須將其轉(zhuǎn)換成駝峰大小寫形式宏浩,才能通過(guò) JavaScript 來(lái)訪問(wèn)。
      • 多數(shù)情況下靠瞎,都可以通過(guò)簡(jiǎn)單地轉(zhuǎn)換屬性名的格式來(lái)實(shí)現(xiàn)轉(zhuǎn)換比庄。其中一個(gè)不能轉(zhuǎn)換的 CSS 屬性就是 float 。DOM 2 Style 規(guī)范規(guī)定樣式對(duì)象上相應(yīng)的屬性名應(yīng)該是 cssFloat乏盐,在 IE 上是 styleFloat 佳窑。
      • 在混雜模式下,沒(méi)有給出度量單位的值父能,將默認(rèn)為 px 神凑,但是在標(biāo)準(zhǔn)模式下,這樣的值會(huì)被忽略何吝。
    • DOM 2 Style 規(guī)范為 style 對(duì)象定義了一些屬性和方法溉委。這些屬性和方法在提供元素的 style 特性值的同時(shí),也可以修改樣式:
      • cssText:訪問(wèn) style 特性中的 CSS 代碼(可讀可寫)岔霸。
      • length:應(yīng)用給元素的 CSS 屬性的數(shù)量
      • parentRule:表示 CSS 信息的 CSSRule 對(duì)象薛躬。
      • getPropertyCSSValue(propertyName):返回包含給定屬性值的 CSSValue 對(duì)象。
        • CSSValue 包含兩個(gè)屬性:cssTextcssValueType 呆细; cssValueType 是一個(gè)數(shù)值常量型宝,表示值的類型:0 - 繼承的值八匠,1 - 基本的值,2 - 值列表趴酣, 3 - 自定義的值梨树。
      • getPropertyPriority(propertyName):如果給定的屬性使用了 !important 設(shè)置,則返回 important 岖寞,否則返回空字符串抡四。
      • getPropertyValue(propertyName):返回給定屬性的字符串值。
      • item(index):返回給定位置的 CSS 屬性的名稱仗谆。
      • removeProperty(propertyName):從樣式中刪除給定屬性指巡。
      • setProperty(propertyName, value, priority):將給定屬性設(shè)置為相應(yīng)的值,并加上優(yōu)先權(quán)標(biāo)志( important 或者一個(gè)空字符串)隶垮。
    • DOM 2 Style 增強(qiáng)了 document.defaultView 藻雪,提供了 getComputedStyle() 方法。這個(gè)方法接受兩個(gè)參數(shù):要取得計(jì)算樣式的元素和一個(gè)偽元素字符串(例如: :after )狸吞。如果不需要偽元素信息可以傳入 null 勉耀。這個(gè)方法返回一個(gè) CSSStyleDeclaration 對(duì)象,其中包含當(dāng)前元素的所有計(jì)算后的樣式蹋偏。
      • 由于瀏覽器解釋綜合( rollup )屬性的方式不同便斥,所以類似 border 這樣的綜合屬性,不會(huì)在所有瀏覽器中都有返回值威始,但是可以通過(guò)分別訪問(wèn)四個(gè)邊的屬性(例如 .borderLeftWidth )得到值枢纠。
      • IE 不支持 getComputedStyle() 方法,但它有一種類似的概念黎棠。在 IE 中京郑,每個(gè)具有 style 屬性的元素還有一個(gè) currentStyle 屬性。這個(gè)屬性是 CSSStyleDeclaration 的實(shí)例葫掉,包含當(dāng)前元素全部計(jì)算后的樣式些举。
    • 不能指望某個(gè) CSS 屬性的默認(rèn)值在不同瀏覽器中是相同的,比如 visibility 屬性在有些瀏覽器中默認(rèn)值是 visible 俭厚,有些是 inherit户魏。如果你需要元素具有某個(gè)特定的默認(rèn)值,應(yīng)該手工在樣式表中指定該值挪挤。
  3. 操作樣式表

    • CSSStyleSheet 類型表示的是樣式表叼丑,包括通過(guò) <link> 元素包含的樣式表和在 <style> 元素中定義的樣式表。它只表示樣式表扛门,不管這些樣式表在 HTML 中是如何定義的鸠信。此外,這個(gè)對(duì)象是一套只讀接口(有一個(gè)屬性例外)论寨。使用下列代碼確認(rèn)瀏覽器是否支持 DOM2 StyleSheet:

      var supportsDOM2StyleSheet = document.implementation.hasFeature('StyleSheets', '2.0')
      
      • CSSStyleSheet 繼承自 StyleSheet 星立,所以我們可以使用后者作為基礎(chǔ)接口來(lái)定義非 CSS 樣式表爽茴。從 StyleSheet 接口繼承而來(lái)的屬性如下:

        • disabled:表示樣式表是否被禁用。這個(gè)屬性是可讀 / 可寫的绰垂,將這個(gè)屬性設(shè)置為 true 可以禁用樣式表室奏。
        • href:如果樣式表是通過(guò) <link> 包含的,則是樣式表的 URL 劲装,否則胧沫,是 null
        • media:當(dāng)前樣式表支持的所有媒體類型(MIME Type)的集合占业。如果集合是空列表绒怨,表示樣式表適用于所有媒體。在 IE 中谦疾,media 是一個(gè)反映 <link><style> 元素 media 特性值的字符串窖逗。
        • ownerNode:指向擁有當(dāng)前樣式表的節(jié)點(diǎn)的指針,樣式表可能是在 HTML 中通過(guò) <link><style /> 引入的(在 XML 中可能是通過(guò)處理指令引入的)餐蔬。如果當(dāng)前樣式表是通過(guò)其他樣式表通過(guò) @import 導(dǎo)入的,則這個(gè)屬性值為 null 佑附。IE 不支持這個(gè)屬性樊诺。
        • parentStyleSheet:在當(dāng)前樣式表是通過(guò) @import 導(dǎo)入的情況下,這個(gè)屬性是一個(gè)指向?qū)胨臉邮奖淼闹羔槨?/li>
        • titleownerNodetitle 屬性的值音同。
        • type:表示樣式表類型的字符串词爬。CSS 是 type/css

        以上屬性权均,除了 disabled 之外顿膨,都是只讀的。同時(shí)叽赊,CSSStyleSheet 還支持下列屬性和方法:

        • cssRules:樣式表中包含的樣式規(guī)則的合集恋沃。IE 不支持這個(gè)屬性,但是提供了一個(gè)類似的 rules 屬性必指。
        • ownerRules:如果樣式表是通過(guò) @import 導(dǎo)入的囊咏,這個(gè)屬性就是一個(gè)指針,指向表示導(dǎo)入的規(guī)則塔橡;否則梅割,值為 null 。IE 不支持這個(gè)屬性葛家。
        • deleteRule(index):刪除 cssRules 集合中指定位置的規(guī)則户辞。IE 不支持,但提供了一個(gè)類似的 removeRule() 方法癞谒。
        • insertRule(rule, index):向 cssRules 集合中指定的位置插入 rule 字符串底燎。IE 不支持刃榨,但提供了一個(gè)類似的 addRule() 方法。
        for (let i = 0; i < document.styleSheets.length; i++) {
            const sheet = document.styleSheets[i]
            console.log(sheet.href)
        }
        
      • 可以直接通過(guò) <link><style> 元素取得 CSSStyleSheet 對(duì)象书蚪。DOM 規(guī)定了一個(gè)包含 CSSStyleSheet 對(duì)象的屬性喇澡,叫 sheet 。除了 IE 殊校,其他瀏覽器都支持這個(gè)屬性晴玖。IE 支持的是 styleSheet 屬性。要想在不同瀏覽器中都能取得樣式表對(duì)象为流,可以使用如下代碼:

        function getStyleSheet (element) {
            return element.sheet || element.styleSheet
        }
        const link = document.getElementsByTagName('link')[0]
        const sheet = getStyleSheet(link)
        
    • CSSRule 對(duì)象表示樣式表中的每一條規(guī)則呕屎。實(shí)際上,CSSRule 是一個(gè)供其他多種類繼承的基類型敬察,其中最常見的是 CSSStyleRule 類型秀睛,表示樣式表信息(其他規(guī)則還有 @import@font-face莲祸、@page@charset 蹂安,但這些規(guī)則很少有必要通過(guò)腳本來(lái)訪問(wèn)。)CSSStyleRule 對(duì)象包含以下屬性:

      • cssText:返回整條規(guī)則對(duì)應(yīng)的文本锐帜。由于瀏覽器對(duì)樣式表的內(nèi)部處理方式不同田盈,返回的文本可能會(huì)與樣式表中實(shí)際的文本不一樣。Safari 會(huì)全部轉(zhuǎn)換為小寫缴阎,IE 不支持這個(gè)屬性允瞧。
        • cssText 包含選擇符文本和圍繞樣式信息的花括號(hào)且只讀,style.cssText 只包含樣式信息且可被修改蛮拔。
      • parentRule:如果當(dāng)前規(guī)則是導(dǎo)入規(guī)則述暂,這個(gè)屬性引用的就是導(dǎo)入規(guī)則;否則建炫,這個(gè)值為 null 畦韭。IE 不支持這個(gè)屬性。
      • parentStyleSheet:當(dāng)前規(guī)則所屬的樣式表肛跌。IE 不支持這個(gè)屬性廊驼。
      • ?selectorText:返回當(dāng)前規(guī)則的選擇符文本。由于瀏覽器對(duì)樣式表的內(nèi)部處理方式不同惋砂,返回的文本可能會(huì)與樣式表中實(shí)際的文本不一樣妒挎。
      • style:一個(gè) CSSStyleDeclaration 對(duì)象,可以通過(guò)它設(shè)置和取得規(guī)則中特定的樣式值西饵。
      • type:表示規(guī)則類型的常量值酝掩。對(duì)于樣式規(guī)則,這個(gè)值是 1眷柔。IE 不支持這個(gè)屬性期虾。
      const sheet = document.styleSheets[0]
      const rules = sheet.cssRules || sheet.rules
      const rule = rules[0]
      console.log(rule.cssText)
      console.log(rule.style.cssText)
      
    • DOM 規(guī)定原朝,要向現(xiàn)有樣式表中添加新規(guī)則,需要使用 insertRule() 方法镶苞。這個(gè)方法接受兩個(gè)參數(shù):規(guī)則文本和表示在哪里插入規(guī)則的索引:

      sheet.insertRule('body { background-color: #fff }', 0)
      

      上述語(yǔ)句的插入的規(guī)則將成為樣式表中的第一條規(guī)則(插入到了位置 0)喳坠。
      IE 8 及更早的版本支持一個(gè)類似的方法,名叫 addRule() 茂蚓,也接受兩個(gè)必選參數(shù):選擇符文本和 CSS 樣式信息振定;一個(gè)可選參數(shù):插入規(guī)則的位置:

      sheet.addRule('body', 'background-color: #fff', 0)
      

      最多只能使用這個(gè)方法插入 4095 條樣式規(guī)則毕籽。

    • 使用 deleteRule() 刪除規(guī)則劫笙。這個(gè)方法接受一個(gè)參數(shù):要?jiǎng)h除的規(guī)則的位置溉躲。IE 支持的類似方法叫 removeRule() ,使用方法相同牍白。

  4. 元素大小

    • DOM 中沒(méi)有規(guī)定如何確定頁(yè)面中元素的大小脊凰,所以下邊的內(nèi)容并不屬于 DOM 2 Style 規(guī)范。IE 最早引入了一些屬性茂腥,目前狸涌,所有主要瀏覽器都支持這些屬性。

    • 偏移量( offset dimension ):包括元素在屏幕上占用的所有可見空間最岗。元素的可見大小由其高度帕胆、寬度決定,包括所有內(nèi)邊距仑性、滾動(dòng)條和邊框大小(不包括外邊距)右蹦。通過(guò)下列四個(gè)屬性可以取得元素的偏移量:

      • offsetHeight:元素在垂直方向上占用的空間大小诊杆,以像素計(jì)。
      • offsetWidth:元素在水平方向占用的空間大小何陆。
      • offsetLeft:元素的左外邊框至包含元素的左內(nèi)邊框之間的像素距離晨汹。
      • offsetTop:元素的上外邊框至包含元素的上內(nèi)邊框之間的像素距離。
        • offsetLeftoffsetTop 與包含元素有關(guān)贷盲。包含元素的引用保存在 offsetParent 屬性中淘这。這個(gè)屬性不一定與 parentNode 的值相等。例如:<td> 元素的 offsetParent 是作為其祖先元素的 <table> 元素巩剖,因?yàn)?<table> 是在 DOM 層次中距 <td> 最近的一個(gè)具有大小的元素铝穷。
        • 要想知道某個(gè)元素在頁(yè)面上的偏移量,將這個(gè)元素的 offsetLeftoffsetTop 與其 offsetParent 的相同屬性相加佳魔,如此循環(huán)直至根元素曙聂,就可以得到一個(gè)基本準(zhǔn)確的值。

      所有這些偏移量屬性都是只讀的鞠鲜,并且每次訪問(wèn)時(shí)都要重新計(jì)算宁脊。為了減少內(nèi)存開銷断国,我們可以將這些偏移量保存在局部變量中。

    • 客戶區(qū)大杏馨( client dimension ):元素內(nèi)容及其內(nèi)邊距所占據(jù)的空間大小稳衬。包含兩個(gè)屬性:

      • clientWidth:元素內(nèi)容區(qū)寬度加上左右內(nèi)邊距寬度。
      • clientHeight:元素內(nèi)容區(qū)高度加上上下內(nèi)邊距高度坐漏。

      確定瀏覽器視口大斜【巍:

      function getViewport () {
          if (document.compatMode == 'BackCompat') { // 是否運(yùn)行在混雜模式
              return {
                  width: document.body.clientWidth,
                  height: document.body.clientHeight
              }
          } else {
              return {
                  width: document.documentElement.clientWidth,
                  height: document.documentElement.clientHeight
              }
          }
      }
      

      客戶區(qū)大小也是只讀的,也需要重新計(jì)算仙畦。

    • 滾動(dòng)大惺涮椤( scroll dimension ):包含滾動(dòng)內(nèi)容的元素的大小。包含以下四個(gè)屬性:

      • scrollHeight:在沒(méi)有滾動(dòng)條的情況下慨畸,元素內(nèi)容的總高度莱坎。
      • ?scrollWidth:在沒(méi)有滾動(dòng)條的情況下,元素內(nèi)容的總寬度寸士。
      • scrollLeft:被隱藏在內(nèi)容區(qū)域左側(cè)的像素?cái)?shù)檐什。通過(guò)設(shè)置該屬性可以改變?cè)氐臐L動(dòng)位置。
      • scrollTop:被隱藏在內(nèi)容區(qū)域上方的像素?cái)?shù)弱卡。通過(guò)設(shè)置該屬性可以改變?cè)氐臐L動(dòng)位置乃正。
        由于一些兼容性差異,在確定文檔的總高度時(shí)(包括基于視口的最小高度時(shí))婶博,必須取得 scrollWidth / clientWidthscrollHeight / clientHeight 中的最大值瓮具,才能保證在跨瀏覽器的環(huán)境下得到精確的結(jié)果。對(duì)于運(yùn)行在混雜模式下的 IE 凡人,要使用 document.body 代替 document.documentElement 名党。
    • 所有的瀏覽器都提供了 getBoundingClientRect() 方法用來(lái)確定元素大小。這個(gè)方法會(huì)返回一個(gè)矩形對(duì)象挠轴,包含四個(gè)屬性:left传睹、topright岸晦、bottom欧啤。這些屬性給出了元素在頁(yè)面中相對(duì)于視口的位置。在 IE 及更早版本的瀏覽器中启上,文檔左上角的起點(diǎn)坐標(biāo)是 (2, 2) 而其他瀏覽器是 (0, 0) 邢隧。所以需要檢查一下位于 (0, 0) 處元素的位置:

      function getBoundingClientRect (element) {
          if (typeof arguments.callee.offset !== 'number') {
              var scrollTop = document.documentElement.scrollTop
              var temp = document.createElement('div')
              temp.style.cssText = 'position: absolute; left: 0; top: 0;'
              document.body.appendChild(temp)
              arguments.callee.offset = - temp.getBoundingClientRect().top - scrollTop
              document.body.removeChild(temp)
              temp = null
          }
          var rect = element.getBoundingClientRect()
          var offset = arguments.callee.offset
          return {
              left: rect.left + offset
              right: rect.right + offset
              top: rect.top + offset
              bottom: rect.bottom + offset
      

      Poly Fill: Custom getBoundingClientRect() method [詳見書 P326]

遍歷

  1. DOM 2 Traversal 定義了兩個(gè)用于輔助完成順序遍歷 DOM 結(jié)構(gòu)的類型:NodeIterator 和 TreeWalker 。這兩個(gè)屬性能夠基于給定的起點(diǎn)對(duì) DOM 結(jié)構(gòu)進(jìn)行深度優(yōu)先遍歷操作冈在。IE 不支持 DOM 遍歷府框。使用下列代碼檢測(cè):

    var supportsTraversals = document.implementation.hasFeature('Traversal', '2.0')
    var supportsNodeIterator = (typeof document.createNodeIterator === 'function')
    var supportsTreeWalker = (typeof document.createTreeWalker === 'function')
    
  2. NodeIterator 類型是兩者中比較簡(jiǎn)單的一個(gè),可以使用 document.createNodeIterator() 方法創(chuàng)建它的新實(shí)例。它接收以下四個(gè)參數(shù):

    • root:想要作為搜索起點(diǎn)的樹中的節(jié)點(diǎn)迫靖。
    • whatToShow:表示要訪問(wèn)哪些節(jié)點(diǎn)的數(shù)字代碼院峡。
      • 它的參數(shù)是一個(gè)位掩碼,通過(guò)應(yīng)用一個(gè)或多個(gè)過(guò)濾器( filter )來(lái)確定要訪問(wèn)哪些節(jié)點(diǎn)系宜。這個(gè)參數(shù)的值以常量形式在 NodeFilter 類型中定義照激,如下所示:

        • NodeFilter.SHOW_ALL:顯示所有類型的節(jié)點(diǎn)。
        • NodeFilter.SHOW_ELEMENT:顯示元素節(jié)點(diǎn)盹牧。
        • NodeFilter.SHOW_ATTRIBUTE:顯示特性節(jié)點(diǎn)俩垃。由于 DOM 結(jié)構(gòu)原因,實(shí)際上不能使用這個(gè)值汰寓。
        • NodeFilter.SHOW_TEXT:顯示文本節(jié)點(diǎn)口柳。
        • NodeFilter.SHOW_CDATA_SECTION:顯示 CDATA 節(jié)點(diǎn)。對(duì) HTML 頁(yè)面沒(méi)有作用有滑。
        • NodeFilter.SHOW_ENTITY_REFERENCE:顯示實(shí)體引用節(jié)點(diǎn)跃闹。對(duì) HTML 頁(yè)面沒(méi)有作用。
        • NodeFilter.SHOW_ENTITY:顯示實(shí)體節(jié)點(diǎn)毛好。對(duì) HTML 頁(yè)面沒(méi)有作用望艺。
        • NodeFilter.SHOW_PROCESSING_INSTRUCTION:顯示處理指令節(jié)點(diǎn)。對(duì) HTML 頁(yè)面沒(méi)有作用肌访。
        • NodeFilter.SHOW_COMMENT:顯示注釋節(jié)點(diǎn)找默。
        • NodeFilter.SHOW_DOCUMENT:顯示文檔節(jié)點(diǎn)。
        • NodeFilter.SHOW_DOCUMENT_TYPE:顯示文檔類型節(jié)點(diǎn)吼驶。
        • NodeFilter.SHOW_DOCUMENT_FRAGMENT:顯示文檔片段節(jié)點(diǎn)惩激。對(duì) HTML 頁(yè)面沒(méi)有作用。
        • NodeFilter.SHOW_NOTATION:顯示符號(hào)節(jié)點(diǎn)蟹演。對(duì) HTML 頁(yè)面沒(méi)有作用风钻。

        除了 SHOW_ALL 之外,可以用 | 運(yùn)算符組合多個(gè)選項(xiàng)轨帜。

    • filter:一個(gè) NodeFilter 對(duì)象魄咕,或者一個(gè)表示應(yīng)該接受還是拒絕某種特定節(jié)點(diǎn)的函數(shù)衩椒。
      • 每個(gè) FilterNode 對(duì)象只有一個(gè)方法蚌父,即 acceptNode() 。如果應(yīng)該訪問(wèn)給定的節(jié)點(diǎn)毛萌,該方法返回 NodeFilter.FILTER_ACCEPT 苟弛,如果不應(yīng)該則返回 NodeFilter.FILTER_SKIP 。這是一個(gè)抽象類型阁将,不能直接創(chuàng)建它的實(shí)例膏秫。在必要時(shí),只要?jiǎng)?chuàng)建一個(gè)包含 acceptNode() 方法的對(duì)象做盅,然后將這個(gè)對(duì)象傳入 createNodeIterator() 中即可缤削。
    • entityReferenceExpansion:布爾值窘哈,表示是否要擴(kuò)展實(shí)體引用。這個(gè)參數(shù)在 HTML 頁(yè)面中沒(méi)有用亭敢,因?yàn)槠渲械膶?shí)體引用不能擴(kuò)展滚婉。

    NodeIterator 類型的兩個(gè)主要方法:

    • nextNode():向后前進(jìn)一步,當(dāng)遍歷到最后一個(gè)節(jié)點(diǎn)時(shí)帅刀,返回 null 让腹。
    • previousNode():向前倒退一步,當(dāng)遍歷到根節(jié)點(diǎn)時(shí)扣溺,返回 null 骇窍。

    例子:返回遍歷中遇到的 <li> 元素

    var div = document.getElementById('div1')
    var filter = function (node) {
        return node.tagName.toLowerCase() === 'li' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP
    }
    var iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, filter, false)
    var node = iterator.nextNode()
    while(node !== null) {
        console.log(node.tagName)
        node = iterator.nextNode()
    }
    
  3. TreeWalker 是 NodeIterator 的一個(gè)更高級(jí)的版本。除了包括 nextNode()previousNode() 在內(nèi)的相同功能之外锥余,這個(gè)類型還提供了下列用于在不同方向上遍歷 DOM 結(jié)構(gòu)的方法腹纳。

    • parentNode():遍歷到當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)。
    • firstChild():遍歷到當(dāng)前節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)哈恰。
    • lastChild():遍歷到當(dāng)前節(jié)點(diǎn)的最后一個(gè)子節(jié)點(diǎn)只估。
    • nextSibling():遍歷到當(dāng)前節(jié)點(diǎn)的下一個(gè)同輩節(jié)點(diǎn)。
    • previousSibling():遍歷到當(dāng)前節(jié)點(diǎn)的上一個(gè)同輩節(jié)點(diǎn)着绷。

    創(chuàng)建 TreeWalker 對(duì)象要使用 document.createTreeWalker() 方法蛔钙,這個(gè)方法接受四個(gè)參數(shù),與 document.createNodeIterator 相同荠医。

    • filter 的返回值吁脱,除了 FILTER_ACCEPTFILTER_SKIP 之外,還可以使用 FILTER_REJECT 彬向,在 NodeIterator 中兼贡,NodeFilter.FILTER_SKIPNodeFilter.FILTER_REJECT 作用相同:跳過(guò)指定節(jié)點(diǎn)。但在 TreeWalker 中娃胆,FILTER_SKIP 會(huì)跳過(guò)相應(yīng)節(jié)點(diǎn)繼續(xù)前進(jìn)到子樹中的下一個(gè)節(jié)點(diǎn)遍希,而 FILTER_REJECT 會(huì)跳過(guò)相應(yīng)節(jié)點(diǎn)及該節(jié)點(diǎn)的整個(gè)子樹。

范圍

  1. DOM 2 Traversal & Range 模塊定義了范圍( range )接口里烦。通過(guò)范圍可以選擇文檔中的一個(gè)區(qū)域凿蒜,而不必考慮節(jié)點(diǎn)的界限(選擇在后臺(tái)完成,對(duì)用戶是不可見的胁黑。)IE 實(shí)現(xiàn)范圍特性的方式不同废封。

  2. DOM 2 在 Document 類型中定義了 createRange() 方法。在兼容 DOM 的瀏覽器中丧蘸,這個(gè)方法屬于 document 對(duì)象漂洋。檢測(cè)方法:

    var supportsRange = document.implementation.hasFeature('Range', '2.0')
    var alsoSupportsRange = (typeof document.createRange === 'function')
    
  3. 可以使用 document.createRange() 創(chuàng)建一個(gè) Range 類型的實(shí)例。該實(shí)例包含以下屬性,他們提供了當(dāng)前范圍在文檔中的位置信息:

    • startContainer:包含范圍起點(diǎn)的節(jié)點(diǎn)(即選中區(qū)第一個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn))
    • startOffset:范圍在 startContainer 中起點(diǎn)的偏移量刽漂。如果 startContainer 是文本節(jié)點(diǎn)演训、注釋節(jié)點(diǎn)或 CDATA 節(jié)點(diǎn),那么 startOffset 就是范圍起點(diǎn)之前跳過(guò)的字符數(shù)量贝咙,否則仇祭,就是范圍中第一個(gè)子節(jié)點(diǎn)的索引。
    • endContainer:包含范圍終點(diǎn)的節(jié)點(diǎn)(即選區(qū)中最后一個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn))颈畸。
    • endOffset:范圍在 endContainer 中終點(diǎn)的偏移量(與 startOffset 遵循相同的取值規(guī)則)乌奇。
    • commonAncestorContainerstartContainerendContainer 共同的祖先節(jié)點(diǎn)在文檔樹中位置最深的那個(gè)。
  4. 用 DOM 范圍實(shí)現(xiàn)簡(jiǎn)單選擇:selectNode()selectNodeContents() 眯娱。它們都接收一個(gè)參數(shù)礁苗,即一個(gè) DOM 節(jié)點(diǎn)。然后使用該節(jié)點(diǎn)中的信息來(lái)填充范圍徙缴。其中试伙,selectNode() 方法選擇整個(gè)節(jié)點(diǎn),包括子節(jié)點(diǎn)于样;selectNodeContents() 只選擇節(jié)點(diǎn)的子節(jié)點(diǎn)疏叨。

    var range = document.createRange()
    range.selectNode(document.getElementById('test')
    

    為了更精細(xì)的控制將哪些節(jié)點(diǎn)包含在范圍中,還可以使用下列方法:

    • setStartBefore(refNode):將范圍起點(diǎn)設(shè)置在 refNode 之前穿剖,即 refNode 是范圍選區(qū)中的第一個(gè)子節(jié)點(diǎn)蚤蔓。
    • setStartAfter(refNode):將范圍起點(diǎn)設(shè)置在 refNode 之后,即 refNode 的下一個(gè)同輩節(jié)點(diǎn)是范圍選區(qū)中的第一個(gè)子節(jié)點(diǎn)糊余。
    • ?setEndBefore(refNode):將范圍終點(diǎn)設(shè)置在 refNode 之前秀又,即 refNode 的上一個(gè)同輩節(jié)點(diǎn)是范圍選區(qū)中的最后一個(gè)子節(jié)點(diǎn)。
    • ?setEndAfter(refNode):將范圍終點(diǎn)設(shè)置在 refNode 之后贬芥,即 refNode 是范圍選區(qū)中的最后一個(gè)子節(jié)點(diǎn)吐辙。
  5. 用 DOM 范圍實(shí)現(xiàn)復(fù)雜選擇:setStart()setEnd()。這兩個(gè)方法都接受兩個(gè)參數(shù):參照節(jié)點(diǎn)和偏移量蘸劈,分別對(duì)應(yīng) startContainer / endContainerstartOffset / endOffset 昏苏。

  6. 操作 DOM 范圍中的內(nèi)容:創(chuàng)建范圍時(shí),內(nèi)部會(huì)為這個(gè)范圍創(chuàng)建一個(gè)文檔片段威沫,范圍所屬的全部節(jié)點(diǎn)都被添加到了這個(gè)文檔片段中贤惯。范圍會(huì)自動(dòng)完善 DOM 結(jié)構(gòu),變成一個(gè)有效的 DOM 壹甥。于是救巷,就可以使用下列方法進(jìn)行操作了:

    • deleteContents:從文檔中刪除范圍所包含的內(nèi)容壶熏。
    • extractContents:從文檔中移除范圍選區(qū)(返回范圍的文檔片段)句柠。
    • cloneContents:返回范圍中節(jié)點(diǎn)的副本作為文檔片段。
  7. 插入 DOM 范圍中的內(nèi)容:insertNode()

  8. 折疊 DOM 范圍:collapse()

  9. 比較 DOM 范圍:compareBoundaryPoints() 比較是否有公共邊界(起點(diǎn)或終點(diǎn))

  10. 復(fù)制 DOM 范圍:range.cloneRange()

  11. 清理 DOM 范圍:

    range.detach()
    range = null
    
  12. IE 8 及更早版本的范圍
    [詳見書 P340]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市溯职,隨后出現(xiàn)的幾起案子精盅,更是在濱河造成了極大的恐慌,老刑警劉巖谜酒,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叹俏,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡僻族,警方通過(guò)查閱死者的電腦和手機(jī)粘驰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)述么,“玉大人蝌数,你說(shuō)我怎么就攤上這事《让兀” “怎么了顶伞?”我有些...
    開封第一講書人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)剑梳。 經(jīng)常有香客問(wèn)我唆貌,道長(zhǎng),這世上最難降的妖魔是什么垢乙? 我笑而不...
    開封第一講書人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任锨咙,我火速辦了婚禮,結(jié)果婚禮上追逮,老公的妹妹穿的比我還像新娘蓖租。我一直安慰自己,他們只是感情好羊壹,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開白布蓖宦。 她就那樣靜靜地躺著,像睡著了一般油猫。 火紅的嫁衣襯著肌膚如雪稠茂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,954評(píng)論 1 283
  • 那天情妖,我揣著相機(jī)與錄音睬关,去河邊找鬼。 笑死毡证,一個(gè)胖子當(dāng)著我的面吹牛电爹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播料睛,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼丐箩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼摇邦!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起屎勘,我...
    開封第一講書人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤施籍,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后概漱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丑慎,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年瓤摧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了竿裂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡照弥,死狀恐怖铛绰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情产喉,我是刑警寧澤捂掰,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站曾沈,受9級(jí)特大地震影響这嚣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜塞俱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一姐帚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧障涯,春花似錦罐旗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至粘我,卻和暖如春鼓蜒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背征字。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工都弹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人匙姜。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓畅厢,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親氮昧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子框杜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容