<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] # DOM(文檔對象模型) 根據 W3C 的 HTML DOM 標準,HTML 文檔中的所有內容都是節點: - 整個文檔是一個文檔節點 - 每個 HTML 元素是元素節點 - HTML 元素內的文本是文本節點 - 每個 HTML 屬性是屬性節點 - 注釋是注釋節點 # 常用節點類型及其介紹 Document 類型表示整個文檔,是一組分層節點的根節點。在 JavaScript 中,document 對象是 Document 的一個實例。使用 document 對象,有很多種方式可以查詢和取得節點。 Element 節點表示文檔中的所有 HTML 或 XML 元素,可以用來操作這些元素的內容和特性。 另外還有一些節點類型,分別表示文本內容、注釋、文檔類型、CDATA 區域和文檔片段。 ## Element 類型 Element 類型可以說是 Web 編程中最常用的類型 Element 節點具有以下特征: - nodeType 的值為 1; - nodeName 的值為元素的標簽名; - nodeValue 的值為 null; - parentNode 可能是 Document 或 Element; - 其子節點可能是 Element、Text、Comment、ProcessingInstruction、CDATASection 或 EntityReference。 要訪問元素的標簽名,可以使用 nodeName 屬性,也可以使用 tagName 屬性;這兩個屬性會返回相同的值(使用后者主要是為了清晰起見)。需要注意的是 `div.tagName` 實際上輸出的是 'DIV' 而非 'div',所以最好是這么比較 ```js // 這樣最好(適用于任何文檔) if (element.tagName.toLowerCase() == "div"){ // do something... } ``` ### 1.HTML 元素 所有 HTML 元素都由 HTMLElement 類型表示,不是直接通過這個類型,也是通過它的子類型來表 示。HTMLElement 類型直接繼承自 Element 并添加了一些屬性。每個 HTML 元素中都存在的下列標準特性: - id,元素在文檔中的唯一標識符。 - title,有關元素的附加說明信息,一般通過工具提示條顯示出來。 - lang,元素內容的語言代碼,很少使用。 - dir,語言的方向,值為"ltr"(left-to-right,從左至右)或"rtl"(right-to-left,從右至左), 也很少使用。 - className,與元素的 class 特性對應,即為元素指定的 CSS 類。沒有將這個屬性命名為 class,是因為 class 是 ECMAScript 的保留字 ```js <div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr"></div> var div = document.getElementById("myDiv") alert(div.id) // "myDiv"" alert(div.className) // "bd" alert(div.title) // "Body text" alert(div.lang) // "en" alert(div.dir) // "ltr" ``` 所有 HTML 元素都是由 HTMLElement 或者其更具體的子類型來表示的,每一種類型都有與之相關的特性和方法,比如 A 元素和 IMG 元素它們的特性和對應的方法是不完全相同的。 ### 2.取得特性 每個元素都有一或多個特性,這些特性的用途是給出相應元素或其內容的附加信息。操作特性的 DOM 方法主要有三個,分別是 getAttribute()、setAttribute() 和 removeAttribute(),這三個方法可以針對任何特性使用。 `getAttribute()`:由于 `div.getAttribute('id')` 和 `div.id` 的效果是一樣的,所以一般不使用,直接使用后者來訪問元素節點的特性(屬性)即可。 關于自定義特性(一般用 data- 表示)可以通過 dataset 屬性來訪問(當然用 getAttribute 方法也行),比如 ```html <img id="test" src="" class="image-item" lazyload="true" data-original="https://xxx.webp" alt="" /> // document.getElementById('test').dataset.original 可以訪問到 data-original 的值 ``` 參考:[https://blog.csdn.net/qq\_39579242/article/details/81779170](https://blog.csdn.net/qq_39579242/article/details/81779170) ### 3.設置和移除特性 `setAttribute()`:這個方法接受兩個參數:要設置的特性名和值。如果特性已經存在,setAttribute() 會以指定的值替換現有的值;如果特性不存在,setAttribute() 則創建該屬性并設置相應的值。 用法如下: ```js div.setAttribute("id", "someOtherId") div.setAttribute("class", "ft") div.setAttribute("title", "Some other text") ``` > 通過這個方法設置的特性名會被統一轉換為小寫形式,即"ID"最終會變成"id"。 `removeAttribute()`:這個方法用于徹底刪除元素的特性。調用這個方法不僅會清除特性的值,而且也會從元素中完全刪除特性 ``` div.removeAttribute("class"); ``` ### 4.attributes 屬性 Element 類型是使用 attributes 屬性的唯一一個 DOM 節點類型。attributes 屬性中包含一個 NamedNodeMap,與 NodeList 類似。雖然我們可以用它做以上三個方法的操作,但是不是很方便(額外的操作 API),一般在需要遍歷元素的特性時可以使用這個屬性 以下代碼展示了如何迭代元素的每一個特性,然后將它們構造成 name="value" 這樣的字符串格式 ```js // 迭代元素的每一個特性,將它們構造成 name = value 的字符串形式 function outputAttributes (element) { const pairs = [] let attrName let attrValue for (let i = 0, len = element.attributes.length; i < len; i++) { attrName = element.attributes[i].nodeName attrValue = element.attributes[i].nodeValue pairs.push(`${attrName}=${attrValue}`) } return pairs.join(" ") } ``` ### 5.classList 屬性(DOM 擴展) ```html <div class="bd user disabled">...</div> ``` 這個`<div>`元素一共有三個類名。要從中刪除一個類名,需要把這三個類名拆開,刪除不想要的那個,然后再把其他類名拼成一個新字符串。請看下面的例子。 ```js // div.className = 'bd user disabled' let classNames = div.className.split(/\s+/) let pos = -1 for (let i = 0, len = classNames.length; i < len; i++) { if (classNames[i] === 'user') { pos = i break } } classNames.splice(pos, 1) // 刪除類名 div.className = classNames.join(' ') // 把剩下的類名拼接成字符串并重新設置 ``` HTML5 新增了一種操作類名的方式,可以讓操作更簡單也更安全,那就是為所有元素添加 classList 屬性。這個 classList 屬性是新集合類型 DOMTokenList 的實例。與其他 DOM 集合類似 DOMTokenList 有一個表示自己包含多少元素的 length 屬性,而要取得每個元素可以使用 item() 方法,也可以使用方括號語法。此外,這個新類型還定義如下方法。 - add(value):將給定的字符串值添加到列表中。如果值已經存在,就不添加了。 - contains(value):表示列表中是否存在給定的值,如果存在則返回 true,否則返回 false。 - remove(value):從列表中刪除給定的字符串。 - toggle(value):如果列表中已經存在給定的值,刪除它;如果列表中沒有給定的值,添加它。 這樣,前面那么多行代碼用下面這一行代碼就可以代替了 ```js div.classList.remove("user") ``` 其他操作: ```js // 刪除 "disabled" 類 div.classList.remove("disabled") // 添加 "current" 類 div.classList.add("current") // 切換 "user" 類 div.classList.toggle("user") // 確定元素中是否包含既定的類名 if (div.classList.contains("bd") && !div.classList.contains("disabled")) { // do something... ) // 迭代類名 for (var i = 0, len = div.classList.length; i < len; i++) { doSomething(div.classList[i]) } ``` 有了 classList 屬性,除非你需要全部刪除所有類名,或者完全重寫元素的 class 屬性,否則也就用不到 className 屬性了 # 節點關系 ![](https://box.kancloud.cn/e3e6da51171ba916d958366256b7185b_661x335.png) 注意關系指針都是只讀的,見下表 | 關系指針 | 描述 | | :---- | :---- | | childNodes | 每個節點都有一個 childNodes 屬性,其中保存著一個 NodeList 對象,NodeList 是一種類數組對象,用于保存一組有序的節點,可以通過下標來訪問這些節點。 | | parentNode | 指向該節點在文檔樹中的父節點 | | previousSibling | 上一個兄弟,沒有則為 null | | nextSibling | 下一個兄弟,沒有則為 null | | firstChild | 第一個子節點 | | lastChild | 最后一個子節點 | | ownerDocument| 該屬性指向表示整個文檔的文檔節點 | contains() 方法用于判斷某個節點是否為另一個節點的后代,調用 contains 方法的應該是祖先節點,也就是搜索開始的節點,這個方法接收一個參數,即需要檢測的節點。 `console.log(document.documentElement.contains(document.body)) // true` 這個例子檢測了\<body\>元素是不是\<html\>元素的后代 <br> 需要注意的是,用上面的方式訪問節點返回的不一定是元素節點(Element 類型),而我們往往需要操作的只是元素節點,所以就有了以下的 DOM 擴展: Element Traversal API 為 DOM 元素添加了以下 5 個屬性: - childElementCount:返回子元素(不包括文本節點和注釋)的個數。 - firstElementChild:指向第一個子元素;firstChild 的元素版。 - lastElementChild:指向最后一個子元素;lastChild 的元素版。 - previousElementSibling:指向前一個同輩元素;previousSibling 的元素版。 - nextElementSibling:指向后一個同輩元素;nextSibling 的元素版。 支持的瀏覽器為 DOM 元素添加了這些屬性,利用這些元素不必擔心空白文本節點,從而可以更方便地查找 DOM 元素了。 下面來看一個例子。過去,要跨瀏覽器遍歷某元素的所有子元素,需要像下面這樣寫代碼。 ```js let child = element.firstChild while (child !== element.lastChild) { if (child.nodeType === 1) { // 檢查是否為元素節點 processChild(child) } child = child.nextSibling } ``` 而使用 Element Traversal 新增的元素,代碼會更簡潔: ```js let child = element.firstElementChild while (child !== element.lastElementChild) { processChild(child) // 肯定是元素節點 child = child.nextElementSibling // 遍歷下一個元素節點 } ``` # 節點操作 ## 創建節點 ⒈`document.createElement(tagName)`?創建一個元素節點,tagName 為 HTML 標簽的名稱(不區分大小寫,如'div'),并將返回一個節點對象。 ⒉`document.createTextNode(text)`創建一個文本節點,text 為文本節點的內容,并將返回一個節點對象。 ⒊`document.createDocumentFragment()`創建一個文檔片段 文檔片段用于保存將來可能添加到文檔中的節點,可以通過 appendChild() 或 insertBefore() 方法將文檔片段中的內容添加到文檔中。在將文檔片段作為參數傳給這兩個方法時,實際上只有文檔片段的所有子節點會被添加到文檔樹中,**文檔片段本身永遠不會成為文檔樹中的一部分**。 ```js var fragment = document.createDocumentFragment() var ul = document.getElementById('myList') var li = null for (var i = 0; i < 3; i++) { li = document.createElement('li') li.appendChild(document.createTextNode(`Item ${i + 1}`)) fragment.appendChild(li) } ul.appendChild(fragment) ``` 這樣做的好處是:如果逐個地添加列表項,將會導致瀏覽器的反復渲染(呈現)新信息,使用文檔片段可以一次性地將多個節點添加到文檔樹。 ## 獲取元素節點 帶 s 的就是返回一個 NodeList...... ⒈`document.getElementById()`根據 id 獲取節點 ⒉`document.getElementsByTagName()`返回帶有指定標簽名的對象的集合 ⒊`document.getElementsByClassName()`返回文檔中所有指定類名的元素的集合,作為 NodeList 對象 ⒋`document.getElementsByName()`查詢的是元素的 name 屬性 因為一個文檔中的 name 屬性可能不唯一(如 HTML 表單中的單選按鈕通常具有相同的 name 屬性),所以 getElementsByName() 方法返回的是元素的 NodeList,而不是一個元素。 ⒌`document.querySelector()` - 該方法接受一個 CSS 選擇符,返回與該模式匹配的第一個元素,如果沒有找到匹配的元素則返回 null - 選擇符可以為?id、類、?類型、?屬性、?屬性值等。 - 對于多個選擇器,使用逗號隔開,返回一個匹配的元素。 ``` js // 取得 body 元素 var body = document.querySelector("body") // 取得 ID 為 "myDiv" 的元素 var myDiv = document.querySelector("#myDiv") // 取得類為 "selected" 的第一個元素 var selected = document.querySelector(".selected") // 取得類為 "button" 的第一個圖像元素 var img = document.body.querySelector("img.button") // 獲取文檔中 class="example" 的第一個 <p> 元素: document.querySelector("p.example") // 獲取文檔中有 "target" 屬性的第一個 <a> 元素 document.querySelector("a[target]") ``` 注意:通過 Document 類型調用 querySelector() 方法時,會在文檔元素的范圍內查找匹配的元素。而通過 Element 類型調用 querySelector() 方法時,只會在該元素后代元素的范圍內查找匹配的元素。 CSS 選擇符可以簡單也可以復雜,視情況而定。如果傳入了不被支持的選擇符,querySelector() 會拋出錯誤。 ⒍`document.querySelectorAll()` querySelectorAll() 方法接收的參數與 querySelector() 方法一樣,都是一個 CSS 選擇符,但返回的是所有匹配的元素而不僅僅是一個元素。**這個方法返回的是一個 NodeList 的實例**,如果沒有找到匹配的元素則 NodeList 為空。 ``` js // 取得某 <div> 中的所有 <em> 元素(類似于 getElementsByTagName("em")) var ems = document.getElementById("myDiv").querySelectorAll("em") // 取得類為 "selected" 的所有元素 var selecteds = document.querySelectorAll(".selected") // 取得所有<p>元素中的所有<strong>元素 var strongs = document.querySelectorAll("p strong") ``` ## 改變節點關系 | 方法 | 描述 | | :---- | :---- | | appendChild(newNode) | 向 childNodes 列表末尾添加一個節點,添加節點后,childNodes 的新增節點、父節點以及最后一個節點的關系指針都會相應地得到更新。更新完成后,該方法返回新增的節點 | | insertBefore(newNode, 參照 Node) | 該方法接收兩個參數:要插入的節點和作為參照的節點。插入節點后,插入的節點會成為參照節點的 previousSibling,同時被方法返回。 | | replaceChild(要插入的節點,要替換的節點) | 要替換的節點將由這個方法返回并從文檔樹中被移除,同時由要插入的節點占據其位置 | | removeChild(要移除的節點) | 被移除的節點將成為方法的返回值 | 這四個方法操作的都是某個節點的子節點,也就是說,要使用這幾個方法必須先取得父節點(使用 parentNode 屬性)。另外,并不是所有類型的節點都有子節點,如果在不支持子節點的節點上調用了這些方法,將會導致錯誤發生。 # DOM 操作技術 ## 動態腳本 ```js function loadScript (url) { var script = document.createElement("script") script.type = "text/javascript" script.src = url document.body.appendChild(script) } ``` ## 動態樣式 ```js function loadStyles (url) { var link = document.createElement("link") link.rel = "stylesheet" link.type = "text/css" link.href = url var head = document.getElementsByTagName("head")[0] head.appendChild(link) } ``` href 表示超文本引用(hypertext reference),在 link 和 a 等元素上使用。src 表示來源地址,在 img、script、iframe 等元素上。 src 的內容,是頁面必不可少的一部分,是引入。href 的內容,是與該頁面有關聯,是引用。兩者的區別就是對于當前頁面來說是引入還是引用(只是從意義上講)。 ## 使用 NodeList 理解 NodeList 及其“近親” NamedNodeMap 和 HTMLCollection,是從整體上透徹理解 DOM 的關鍵所在。這三個集合都是“動態的”;換句話說,每當文檔結構發生變化時,它們都會得到更新。因此,它們始終都會保存著最新、最準確的信息。從本質上說,所有 NodeList 對象都是在訪問 DOM 文檔時實時運行的查詢。例如,下列代碼會導致無限循環 ```js var divs = document.getElementsByTagName("div"), i, div for (i=0; i < divs.length; i++) { div = document.createElement("div") document.body.appendChild(div) } ``` 第一行代碼會取得文檔中所有 \<div> 元素的 HTMLCollection。由于這個集合是“動態的”,因此只要有新 \<div> 元素被添加到頁面中,這個元素也會被添加到該集合中。瀏覽器不會將創建的所有集合都保存在一個列表中,而是在下一次訪問集合時再更新集合。結果,在遇到上例中所示的循環代碼時,就會導致一個有趣的問題。每次循環都要對條件 i < divs.length 求值,意味著會運行取得所有 \<div> 元素的查詢。考慮到循環體每次都會創建一個新 \<div> 元素并將其添加到文檔中,因此 divs.length 的值在每次循環后都會遞增。既然 i 和 divs.length 每次都會同時遞增,結果它們的值永遠也不會相等。 如果想要迭代一個 NodeList,最好是使用 length 屬性初始化第二個變量,然后將迭代器與該變量進行比較,如下面的例子所示: ```js var divs = document.getElementsByTagName("div"), i, len, div for (i = 0, len = divs.length; i < len; i++) { div = document.createElement("div") document.body.appendChild(div) } ``` 一般來說,應該盡量減少訪問 NodeList 的次數。因為每次訪問 NodeList,都會運行一次基于文檔的查詢。所以,可以考慮將從 NodeList 中取得的值緩存起來 ## 焦點管理 HTML5 也添加了輔助管理 DOM 焦點的功能。首先就是 document.activeElement 屬性,這個屬性始終會引用 DOM 中當前獲得了焦點的元素。元素獲得焦點的方式有頁面加載、用戶輸入(通常是通過按 Tab 鍵)和在代碼中調用 focus() 方法。來看幾個例子。 ```js var button = document.getElementById("myButton") button.focus() alert(document.activeElement === button) // true ``` 默認情況下,文檔剛剛加載完成時,document.activeElement 中保存的是 document.body 元素的引用。文檔加載期間,document.activeElement 的值為 null。 另外就是新增了 document.hasFocus() 方法,這個方法用于確定文檔是否獲得了焦點 ```js var button = document.getElementById("myButton") button.focus() alert(document.hasFocus()) // true ``` 通過檢測文檔是否獲得了焦點,可以知道用戶是不是正在與頁面交互。查詢文檔獲知哪個元素獲得了焦點,以及確定文檔是否獲得了焦點,這兩個功能最重要的用途是提高 Web 應用的無障礙性。無障礙 Web 應用的一個主要標志就是恰當的焦點管理,而確切地知道哪個元素獲得了焦點是一個極大的進步,至少我們不用再像過去那樣靠猜測了。 ## 自定義數據屬性 HTML5 規定可以為元素添加非標準的屬性,但要添加前綴 data-,目的是為元素提供與渲染無關的信息,或者提供語義信息。這些屬性可以任意添加、隨便命名,只要以 data-開頭即可。來看一個例子 ```html <div id="myDiv" data-appId="12345" data-myname="Nicholas"></div> ``` 添加了自定義屬性之后,可以通過元素的 dataset 屬性來訪問自定義屬性的值。dataset 屬性的值是 DOMStringMap 的一個實例,也就是一個名值對兒的映射。在這個映射中,每個 data-name 形式的屬性都會有一個對應的屬性,只不過屬性名沒有 data-前綴(比如,自定義屬性是 data-myname, 那映射中對應的屬性就是 myname)。還是看一個例子吧 ```js // 本例中使用的方法僅用于演示 var div = document.getElementById("myDiv") // 取得自定義屬性的值 var appId = div.dataset.appId var myName = div.dataset.myname // 設置值 div.dataset.appId = 23456 div.dataset.myname = "Michael" // 有沒有"myname"值呢? if (div.dataset.myname) { alert("Hello, " + div.dataset.myname) } ``` 如果需要給元素添加一些不可見的數據以便進行其他處理,那就要用到自定義數據屬性。在跟蹤鏈接或混搭應用中,通過自定義數據屬性能方便地知道點擊來自頁面中的哪個部分 ## innerHTML 與 outerHTML ### innerHTML 在讀模式下,innerHTML 屬性返回與調用元素的所有子節點(包括元素、注釋和文本節點)對應的 HTML 標記。在寫模式下,innerHTML 會根據指定的值創建新的 DOM 樹,然后用這個 DOM 樹完全替換調用元素原先的所有子節點。下面是一個例子 ```html <div id="content"> <p>This is a <strong>paragraph</strong> with a list following it.</p> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> </div> 對于上面的<div>元素來說,它的 innerHTML 屬性會返回如下字符串。 <p>This is a <strong>paragraph</strong> with a list following it.</p> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> ``` 但是,不同瀏覽器返回的文本格式會有所不同。IE 和 Opera 會將所有標簽轉換為大寫形式,而 Safari、 Chrome 和 Firefox 則會原原本本地按照原先文檔中(或指定這些標簽時)的格式返回 HTML,包括空格 和縮進。不要指望所有瀏覽器返回的 innerHTML 值完全相同。 在寫模式下,innerHTML 的值會被解析為 DOM 子樹,替換調用元素原來的所有子節點。因為它的值被認為是 HTML,所以其中的所有標簽都會按照瀏覽器處理 HTML 的標準方式轉換為元素(同樣, 這里的轉換結果也因瀏覽器而異)。如果設置的值僅是文本而沒有 HTML 標簽,那么結果就是設置純文本。 ### outerHTML 在讀模式下,outerHTML 返回調用它的元素及所有子節點的 HTML 標簽。在寫模式下,outerHTML 會根據指定的 HTML 字符串創建新的 DOM 子樹,然后用這個 DOM 子樹完全替換調用元素。 使用 outerHTML 屬性以下面這種方式設置值: ```html div.outerHTML = "<p>This is a paragraph.</p>"; ``` 這行代碼完成的操作與下面這些 DOM 腳本代碼一樣: ```js var p = document.createElement("p") p.appendChild(document.createTextNode("This is a paragraph.")) div.parentNode.replaceChild(p, div) ``` 結果,就是新創建的 \<p> 元素會取代 DOM 樹中的 \<div> 元素。 一般來說,在插入大量新 HTML 標記時,使用 innerHTML 屬性與通過多次 DOM 操作先創建節點再指定它們之間的關系相比,效率要高得多。這是因為在設置 innerHTML 或 outerHTML 時,就會創建一個 HTML 解析器。這個解析器是在瀏覽器級別的代碼(通常是 C++ 編寫的)基礎上運行的,因此比執行 JavaScript 快得多。不可避免地,創建和銷毀 HTML 解析器也會帶來性能損失,所以最好能夠將設置 innerHTML 或 outerHTML 的次數控制在合理的范圍內。例如,下列代碼使用 innerHTML 創建了很多列表項: ``` for (var i = 0, len = values.length; i < len; i++) { ul.innerHTML += "<li>" + values[i] + "</li>" // 要避免這種頻繁操作!! } ``` 這種每次循環都設置一次 innerHTML 的做法效率很低。而且,每次循環還要從 innerHTML 中讀取一次信息,就意味著每次循環要訪問兩次 innerHTML。最好的做法是單獨構建字符串,然后再一次性地將結果字符串賦值給 innerHTML,像下面這樣: ```js var itemsHtml = "" for (var i = 0, len = values.length; i < len; i++) { itemsHtml += "<li>" + values[i] + "</li>" } ul.innerHTML = itemsHtml ``` 這個例子的效率要高得多,因為它只對 innerHTML 執行了一次賦值操作 ## scrollIntoView() 方法 scrollIntoView() 可以在所有 HTML 元素上調用,通過滾動瀏覽器窗口或某個容器元素,調用元素就可以出現在視口中。如果給這個方法傳入 true 作為參數,或者不傳入任何參數,那么窗口滾動之后會讓調用元素的頂部與視口頂部盡可能平齊。如果傳入 false 作為參數,調用元素會盡可能全部出現在視口中,(可能的話,調用元素的底部會與視口頂部平齊。)不過頂部不一定平齊,例如: ``` // 讓元素可見 document.forms[0].scrollIntoView() ``` 當頁面發生變化時,一般會用這個方法來吸引用戶的注意力。實際上,**為某個元素設置焦點也會導致瀏覽器滾動并顯示出獲得焦點的元素** ## 訪問元素的樣式 對于使用短劃線(分隔不同的詞匯,例如 background-image)的 CSS 屬性名,必須將其轉換成駝峰大小寫形式,才能通過 JavaScript 來訪問。下表列出了幾個常見的 CSS 屬性及 其在 style 對象中對應的屬性名。 | CSS 屬性 | JavaScript 屬性 | | --- | --- | | background-image | style.backgroundImage | | color | style.color| | display | style.display | | font-family | style.fontFamily| # 元素大小 ## 偏移量 首先要介紹的屬性涉及偏移量(offset dimension),包括元素在屏幕上占用的所有可見的空間。元素的可見大小由其高度、寬度決定,包括所有內邊距、滾動條和邊框大小(注意,不包括外邊距)。通過下列 4 個屬性可以取得元素的偏移量。 - offsetHeight:元素在垂直方向上占用的空間大小,以像素計。包括元素的高度、(可見的)水平滾動條的高度、上邊框高度和下邊框高度。 - offsetWidth:元素在水平方向上占用的空間大小,以像素計。包括元素的寬度、(可見的)垂直滾動條的寬度、左邊框寬度和右邊框寬度。 - offsetLeft:元素的左外邊框至包含元素的左內邊框之間的像素距離。 - offsetTop:元素的上外邊框至包含元素的上內邊框之間的像素距離。 ![](https://box.kancloud.cn/25813e8ca7ee75147831b0e86d283632_605x346.png) ## 客戶區大小 元素的客戶區大小(client dimension),指的是元素**內容及其內邊距**所占據的空間大小。有關客戶區大小的屬性有兩個:clientWidth 和 clientHeight。其中,clientWidth 屬性是元素內容區寬度加上左右內邊距寬度;clientHeight 屬性是元素內容區高度加上上下內邊距高度。下圖形象地說明 了這些屬性表示的大小。 ![](https://box.kancloud.cn/e48023b6abe1f39ad7b8147c1564c426_575x345.png) 可以用來確認瀏覽器視口大小(這不是用 window.innerWidth 和 window.innerHeight 就行了嗎?) ```js function getViewport() { return { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight } } ``` ## 滾動大小 以下是 4 個與滾動大小相關的屬性: - scrollHeight:在沒有滾動條的情況下,元素內容的總高度。 - scrollWidth:在沒有滾動條的情況下,元素內容的總寬度。 - scrollLeft:被隱藏在內容區域左側的像素數。通過設置這個屬性可以改變元素的滾動位置。 - scrollTop:被隱藏在內容區域上方的像素數。通過設置這個屬性可以改變元素的滾動位置 ![](https://box.kancloud.cn/39713029899f60e71bf608f8ac365562_647x393.png) 通過 scrollLeft 和 scrollTop 屬性既可以確定元素當前滾動的狀態,也可以設置元素的滾動位置。在元素尚未被滾動時,這兩個屬性的值都等于 0。如果元素被垂直滾動了,那么 scrollTop 的值會大于 0,且表示元素上方不可見內容的像素高度。如果元素被水平滾動了,那么 scrollLeft 的值會大于 0,且表示元素左側不可見內容的像素寬度。這兩個屬性都是可以設置的,因此將元素的 scrollLeft 和 scrollTop 設置為 0,就可以重置元素的滾動位置。下面這個函數會檢測元素是否位于頂部,如果不是就將其回滾到頂部。 ```js function scrollToTop (element) { if (element.scrollTop != 0) { element.scrollTop = 0 } } ``` 這個函數既取得了 scrollTop 的值,也設置了它的值 ### 滾動方法 `scrollTo(x, y)`:滾動當前 window 中顯示的文檔,讓文檔中由坐標 x 和 y 指定的點位于顯示區域的左上角 `scrollBy(x, y)`:滾動當前 window 中顯示的文檔,x 和 y 指定滾動的相對量 【應用】:利用 scrollBy() + setInterval 實現快速滾動的功能 ```html <body style="height:1000px"> <button id='btn1' style="position:fixed">開始滾動</button> <button id='btn2' style="position:fixed;top:40px">停止滾動</button> <script> var timer = 0; btn1.onclick = function(){ timer = setInterval(function(){ scrollBy(0,10); },100)} btn2.onclick = function(){ clearInterval(timer); timer = 0; } </script> ``` `scrollIntoView()`:方法滾動當前元素,使其進入瀏覽器的可見區域;該方法可以接受一個布爾值作為參數。如果為 true,表示元素的頂部與當前區域的可見部分的頂部對齊(前提是當前區域可滾動);如果為 false,表示元素的底部與當前區域的可見部分的尾部對齊(前提是當前區域可滾動)。如果沒有提供該參數,默認為 true ### 滾動條 參考資料:[CSS 滾動條](https://www.cnblogs.com/xiaohuochai/p/5294409.html) 自定義滾動條樣式: 【1】、IE ```css scrollbar-face-color 滾動條凸出部分的顏色 scrollbar-shadow-color 立體滾動條陰影的顏色 scrollbar-highlight-color 滾動條空白部分的顏色 scrollbar-3dlight-color 滾動條亮邊的顏色 scrollbar-darkshadow-color 滾動條強陰影的顏色 scrollbar-track-color 滾動條的背景顏色 scrollbar-arrow-color 上下按鈕上三角箭頭的顏色 scrollbar-base-color 滾動條的基本顏色 ``` 【2】、webkit webkit 內核的瀏覽器支持滾動條自定義樣式,但和 IE 不同,webkit 是通過偽類來實現的 ```css ::-webkit-scrollbar 滾動條整體部分 ::-webkit-scrollbar-thumb 滾動滑塊 ::-webkit-scrollbar-track 外層軌道 ::-webkit-scrollbar-track-piece 內層軌道 ::-webkit-scrollbar-corner 邊角 ::-webkit-scrollbar-button 兩端按鈕 ``` 常用的樣式設置 ```css ::-webkit-scrollbar { // 去掉滾動條 display: none; } ``` 我們經常會需要一個回到頂部的效果,可以使用`scroll-behavior`來快捷地實現 ```css scroll-behavior: smooth; ``` 當用戶手動導航或者 CSSOM scrolling API 觸發滾動操作時,`scroll-behavior`為一個滾動框指定滾動行為,其他任何的滾動,例如那些由于用戶行為而產生的滾動,不受這個屬性的影響。在根元素中指定這個屬性時,它反而適用于視窗。具體見 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/CSS/scroll-behavior)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看