JavaScript-DOM详解

352 阅读8分钟

一、对DOM理解

DOM:文档对象模型(Document Object Model)

  • 浏览器可以对编写的HTML、CSS进行渲染,同时它又要考虑通过JavaScript来对其进行操作:

    • 浏览器将编写在HTML中的每一个元素(Element)都抽象成了一个个对象

    • 所有这些对象都可以通过JavaScript来对其进行访问,那么就可以通过JavaScript来操作页面

    • 将这个抽象过程称之为 文档对象模型(Document Object Model)

  • 整个文档被抽象到 document 对象中:

    • 比如document.documentElement对应的是html元素
    • 比如document.body对应的是body元素
    • 比如document.head对应的是head元素
  • 学习DOM,就是在学习如何通过JavaScript对文档进行操作
  • DOM相当于是JavaScript和HTML、CSS之间的桥梁

    • 通过浏览器提供的DOM API,可以对元素以及其中的内容做任何事情

二、document对象

  • Document节点表示的整个载入的网页,它的实例是全局的document对象:

    • 对DOM的所有操作都是从 document 对象开始

    • 它是DOM的入口点,可以从document开始去访问任何节点元素

  • 对于最顶层的html、head、body元素,可以直接在document对象中获取到:

    • html元素:<html> = document.documentElement
    • body元素:<body> = document.body
    • head元素:<head> = document.head
    • 文档声明:<!DOCTYPE html> = document.doctype

三、导航

3.1 节点导航

  • 如果获取到一个节点(Node)后,可以根据这个节点去获取其他的节点,称之为节点之间的导航。

  • 节点之间存在如下的关系:

    • 父节点:parentNode
    • 前兄弟节点:previousSibling
    • 后兄弟节点:nextSibling
    • 子节点:childNodes
    • 第一个子节点:firstChild
    • 最后一个子节点:lastChild image.png

3.2 元素导航

  • 如果获取到一个元素(Element)后,可以根据这个元素去获取其他的元素,称之为元素之间的导航。

  • 元素之间存在如下的关系:

    • 父元素:parentElement
    • 前兄弟节点:previousElementSibling
    • 后兄弟节点:nextElementSibling
    • 子节点:children
    • 第一个子节点:firstElementChild
    • 第二个子节点:lastElementChild

    image.png

3.3 table导航

  • <table> 元素支持 (除了上面给出的,之外) 以下这些属性:

    • table.rows — 元素的集合
    • table.caption/tHead/tFoot — 引用元素 <caption><thead><tfoot>
    • table.tBodies — 元素的集合
  • <thead><tfoot><tbody> 元素提供了 rows 属性:

    • tbody.rows — 表格内部 <tr> 元素的集合
  • <tr>

    • tr.cells — 在给定 <tr> 中的 <td><th> 单元格的集合
    • tr.sectionRowIndex — 给定的 <tr> 在封闭的 <thead>/<tbody>/<tfoot> 中的位置(索引)
    • tr.rowIndex — 在整个表格中 <tr> 的编号(包括表格的所有行)
  • <td><th>

    • td.cellIndex — 在封闭的 中单元格的编号
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        table {
          border-collapse: collapse;
        }
    
        td {
          border: 1px solid #000;
          padding: 8px 12px;
        }
      </style>
    </head>
    <body>
    
      <table>
        <tr>
          <td>1-1</td>
          <td>2-1</td>
          <td>3-1</td>
          <td>4-1</td>
        </tr>
        <tr>
          <td>1-2</td>
          <td>2-2</td>
          <td>3-2</td>
          <td>4-2</td>
        </tr>
        <tr>
          <td>1-3</td>
          <td>2-3</td>
          <td>3-3</td>
          <td>4-3</td>
        </tr>
        <tr>
          <td>1-4</td>
          <td>2-4</td>
          <td>3-4</td>
          <td>4-4</td>
        </tr>
      </table>
    
      <script>
    
        var tableEl = document.body.firstElementChild
    
        // // 1.获取1-1
        // var row1El = tableEl.rows[0]
        // var cell1El = row1El.cells[0]
        // console.log(cell1El)
    
        // // 2.获取2-2
        // var row2El = tableEl.rows[1]
        // var cell2El = row1El.cells[1]
    
        // for循环
        for (var i = 0; i < tableEl.rows.length; i++) {
          var rowEl = tableEl.rows[i]
          var cellEl = rowEl.cells[i]
    
          // 设置样式
          cellEl.style.backgroundColor = "red"
          cellEl.style.color = "white"
        }
    
      </script>
    
    </body>
    </html>
    

    image.png

3.4 form导航

  • <form> 元素可以直接通过document来获取:document.forms

  • <form> 元素中的内容可以通过elements来获取:form.elements

  • 也可以设置表单子元素的name来获取

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
    
      <form action="">
        <input name="account" type="text">
        <input name="password" type="password">
        <input name="hobbies" type="checkbox" checked>
        <select name="fruits">
          <option value="apple">苹果</option>
          <option value="orange">橘子</option>
        </select>
      </form>
    
      <script>
    
        // 1.获取form
        // var formEl = document.body.firstElementChild
        var formEl = document.forms[0]
    
        // 2.获取form中的子元素
        var inputEl = formEl.elements.account
        setTimeout(function() {
          console.log(inputEl.value)
        }, 5000)
    
      </script>
    
    </body>
    </html>
    

四、获取任意元素方法

  • DOM 提供了获取元素的方法:

    • document.getElementsByClassName
    • document.getElementById
    • document.querySelector()
    • document.querySelectorAll()

    image.png

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
      </style>
    </head>
    <body>
      <div class="box">
        <h2>我是标题</h2>
        <div class="container">
          <p>
            我是段落, <span class="keyword">kobe</span> 哈哈哈哈
          </p>
          <p>
            我也是段落, <span class="keyword">john</span> 呵呵呵呵额
          </p>
    
          <div class="article">
            <h3 id="title">我是小标题</h3>
            <p>
              我是文章的内容, 嘿嘿嘿嘿嘿
            </p>
          </div>
        </div>
      </div>
    
      <script>
    
        // 一. 通过导航获取
        // // 1.拿到body
        // var bodyEl = document.body
    
        // // 2.拿到box
        // var boxEl = bodyEl.firstElementChild
    
        // // 3.拿container
        // var containerEl = boxEl.children[1]
    
        // // 4.拿p
        // var pEl = containerEl.children[0]
    
        // // 5.拿到keyword
        // var spanEl = pEl.children[0]
        // spanEl.style.color = "red"
    
        // 二. getElementBy*
        // 1.通过className获取元素
        // var keywordEls = document.getElementsByClassName("keyword")
        // // 修改第一个
        // // keywordEls[0].style.color = "red"
        // // 修改所有的
        // for (var i = 0; i < keywordEls.length; i++) {
        //   keywordEls[i].style.color = "red"
        // }
    
        // 2. 通过id获取元素
        // var titleEl = document.getElementById("title")
        // titleEl.style.color = "orange"
    
    
        // 三.querySelector: 通过选择器查询
        var keywordEl = document.querySelector(".keyword")
        // keywordEls是对象, 可迭代的
        // 可迭代对象: String/数组/节点的列表
        var keywordEls = document.querySelectorAll(".keyword")
        for (var el of keywordEls) {
          el.style.color = "red"
        }
        console.log(keywordEls)
    
        var titleEl = document.querySelector("#title")
        titleEl.style.color = "orange"
    
      </script>
    
    </body>
    </html>
    

五、Node节点常见的属性

  • nodeType属性:

    • nodeType 属性提供了一种获取节点类型的方法
    • 它有一个数值型值(numeric value)
  • 常见的节点类型

    image.png

  • nodeName:获取node节点的名字

    • 对于元素,它的意义与 tagName 相同,所以使用哪一个都是可以的

    • 对于其他节点类型(text,comment 等),它拥有一个对应节点类型的字符串

  • tagName:获取元素的标签名词,仅适用于Element节点

  • innerHTML 属性:将元素中的 HTML 获取为字符串形式;设置元素中的内容

  • outerHTML 属性:包含了元素的完整 HTML

  • textContent 属性:仅仅获取元素中的文本内容

  • innerHTML和textContent的区别:

    • 使用 innerHTML,将其作为HTML插入,带有所有 HTML 标签

    • 使用 textContent,将其作为文本插入,所有符号(symbol)均按字面意义处理

  • nodeValue/data:用于获取非元素节点的文本内容

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
      <!-- 我是注释 -->
      我是文本
      <div class="box">
        <h2>我是标题</h2>
        <p>我是内容, 哈哈哈哈</p>
      </div>
    
      <script>
        // 1.获取三个节点
        var bodyChildNodes = document.body.childNodes
        var commentNode = bodyChildNodes[1]
        var textNode = bodyChildNodes[2]
        var divNode = bodyChildNodes[3]
    
        // 2.节点属性
        // 2.1.nodeType 节点的类型
        for (var node of bodyChildNodes) {
          if (node.nodeType === 8) {
          } else if (node.nodeType === 3) {
          } else if (node.nodeType === 1) {
          }
        }
        console.log(commentNode.nodeType, textNode.nodeType, divNode.nodeType) // 8 3 1
        console.log(Node.COMMENT_NODE)
    
        // 2.2.nodeName 节点的名称
        // tagName: 针对元素(element)
        console.log(commentNode.nodeName, textNode.nodeName, divNode.nodeName)
        console.log(commentNode.tagName, divNode.tagName) // undefined 'DIV'
    
        // 2.3. data(nodeValue)/innerHTML/textContent
        // data针对非元素的节点获取数据
        // innerHTML: 对应的html元素也会获取
        // textContent: 只会获取文本内容
        // console.log(commentNode.data, textNode.data, divNode.data) // 我是注释 我是文本 undefined
        // console.log(divNode.innerHTML)
        // console.log(divNode.textContent)
    
        // 设置文本, 作用是一样
        // 设置文本中包含元素内容, 那么innerHTML浏览器会解析, textContent会当成文本的一部分
        // divNode.innerHTML = "<h2>呵呵呵呵</h2>"
        // divNode.textContent = "<h2>嘿嘿嘿嘿</h2>"
    
        // 2.4.outerHTML
        console.log(divNode.outerHTML)
    
      </script>
    
    </body>
    </html>
    

六、元素的属性

6.1 全局属性

  • hidden属性:全局属性,可以用于设置元素隐藏

  • DOM 元素还有其他属性:

    • value
      • <input><select><textarea>(HTMLInputElement,HTMLSelectElement……)的 value
    • href
      • <a href="...">(HTMLAnchorElement)的 href
    • id
      • 所有元素(HTMLElement)的 “id” 特性(attribute)的值
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
    
      <button class="btn">切换</button>
    
      <!-- hidden属性 -->
      <div id="box" class="cba" title="aaa" style="color: red">
        哈哈哈哈哈
      </div>
    
      <script>
        // 1.获取元素
        var boxEl = document.querySelector("#box")
        var btnEl = document.querySelector(".btn")
    
        // 2.监听btn的点击
        btnEl.onclick = function() {
          // 1.只是隐藏
          // boxEl.hidden = true
          // boxEl.style.display = "none"
    
          // 2.切换
          boxEl.hidden = !boxEl.hidden
        }
    
    
      </script>
    
    </body>
    </html>
    

6.2 attribute

  • 属性attribute的分类:

    • 标准的attribute:某些attribute属性是标准的,比如id、class、title、href、type、value等
    • 非标准的attribute:某些attribute属性是自定义的,比如abc、age、height等
  • 所有的attribute都支持的操作

    • elem.hasAttribute(name) — 检查特性是否存在
    • elem.getAttribute(name) — 获取这个特性值
    • elem.setAttribute(name, value) — 设置这个特性值
    • elem.removeAttribute(name) — 移除这个特性
    • attributes:attr对象的集合,具有name、value属性
  • attribute具备以下特征:

    • 它们的名字是大小写不敏感的(id 与 ID 相同)
    • 它们的值总是字符串类型
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
    
      <div id="abc" class="box" title="box"
           age="18" height="1.88">
        我是box
      </div>
    
      <input type="checkbox" checked="checked">
    
      <script>
    
        var boxEl = document.querySelector(".box")
    
        // 1.所有的attribute都支持的操作
        console.log(boxEl.hasAttribute("AGE"), boxEl.hasAttribute("abc"), boxEl.hasAttribute("id"))
        console.log(boxEl.getAttribute("AGE"), boxEl.getAttribute("abc"), boxEl.getAttribute("id"))
    
        boxEl.setAttribute("id", "cba")
        boxEl.removeAttribute("id")
    
        var boxAttributes = boxEl.attributes
        for (var attr of boxAttributes) {
          console.log(attr.name, attr.value)
        }
    
        // 2.通过getAttribute()一定是字符串类型
        var inputEl = document.querySelector("input")
        console.log(inputEl.getAttribute("checked"))
    
      </script>
    
    </body>
    </html>
    

6.3 property操作

对于标准的attribute,会在DOM对象上创建与其对应的property属性

  • 在大多数情况下,它们是相互作用的

    • 改变property,通过attribute获取的值,会随着改变

    • 通过attribute操作修改,property的值会随着改变

      • 但是input的value修改只能通过attribute的方法(chrome浏览器中修改value比设置attribute优先级更
  • 除非特别情况,大多数情况下,设置、获取attribute,推荐使用property的方式:因为它默认情况下是有类型的

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
    
      <!-- 元素中的属性称之为attribute -->
      <!-- 标准的attribute在对应的对象模型中都有对应的property -->
      <div id="abc" class="box" title="标题"
           age="18" height="1.88">
        我是box
      </div>
    
      <input type="checkbox" checked>
    
      账号: <input class="account" type="text">
      <button class="btn">设置input的值</button>
    
      <script>
    
        // 对象中的属性称之为property
        // var obj = {
        //   // property
        //   name: "zhangsan"
        // }
    
        // 1.通过property获取attribute的值
        // 获取box元素
        var boxEl = document.querySelector(".box")
        console.log(boxEl.id, boxEl.title, boxEl.age, boxEl.height)
    
        // input元素
        var inputEl = document.querySelector("input")
        // if (inputEl.getAttribute("checked")) {
        //   console.log("checkbox处于选中状态")
        // }
        if (inputEl.checked) {
          console.log("checkbox处于选中状态")
        }
        console.log(typeof inputEl.checked)
    
        // 2.attribute和property是相互影响的
        boxEl.id = "aaaaa"
        console.log(boxEl.getAttribute("id"))
    
        boxEl.setAttribute("title", "哈哈哈")
        console.log(boxEl.title)
    
        // 3.比较特殊的情况, input设置值(了解)
        var accountInputEl = document.querySelector(".account")
        var btnEl = document.querySelector(".btn")
        btnEl.onclick = function() {
          accountInputEl.setAttribute("value", "kobe")
          // 优先级更高
          accountInputEl.value = "john"
        }
    
      </script>
    
    </body>
    </html>
    

6.4 class和style

6.4.1 class和style用法区别

  • 有时候需要通过JavaScript来动态修改样式,此时有两个选择:

    • 选择一:在CSS中编写好对应的样式,动态的添加class
    • 选择二:动态的修改style属性
  • 开发中如何选择?

    • 在大多数情况下,如果可以动态修改class完成某个功能,更推荐使用动态class
    • 如果对于某些情况,无法通过动态修改class(比如精准修改某个css属性的值),那么就可以修改style属性

6.4.2 className、classList

  • 元素的class attribute,对应的property并非叫class,而是className:

    • 因为JavaScript早期是不允许使用class这种关键字来作为对象的属性,所以DOM规范使用了className
    • 虽然现在JavaScript已经没有这样的限制,但是并不推荐,并且依然在使用className这个名称
  • 对className进行赋值,它会替换整个类中的字符串

  • 如果需要添加或者移除单个的class,可以使用classList属性,elem.classList 是一个特殊的对象:

    • elem.classList.add (class) :添加一个类
    • elem.classList.remove(class):移除类
    • elem.classList.toggle(class) :如果类不存在就添加类,存在就移除它
    • elem.classList.contains(class):检查给定类,返回 true/false
  • classList是可迭代对象,可以通过for of进行遍历

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        .active {
          color: #fff;
          background-color: #f80;
          font-size: 25px;
        }
      </style>
    </head>
    <body>
    
      <div class="box">
        我是box
      </div>
      <button class="btn">切换</button>
    
      <script>
        var boxEl = document.querySelector(".box")
    
        // 1.方法一: className
        // boxEl.className = "abc"
    
        // 2.方法二: classList操作class
        boxEl.classList.add("abc")
        boxEl.classList.add("active")
        boxEl.classList.remove("abc")
    
        // 需求: box在active之间切换
        var btnEl = document.querySelector(".btn")
        btnEl.onclick = function() {
          // if (boxEl.classList.contains("active")) {
          //   boxEl.classList.remove("active")
          // } else {
          //   boxEl.classList.add("active")
          // }
          boxEl.classList.toggle("active")
        }
      </script>
    </body>
    </html>
    

6.4.3 style的用法

  • 如果需要单独修改某一个CSS属性,可以通过style来操作:

    • 对于多词(multi-word)属性,使用驼峰式 camelCase
  • 如果将值设置为空字符串,会使用CSS的默认样式

  • 多个样式的写法,我们需要使用cssText属性:

    • 不推荐这种用法,因为它会替换整个字符串

6.4.4 getComputedStyle方法

  • 如果需要读取样式:

    • 对于内联样式,是可以通过 style.* 的方式读取到的
    • 对于style、css文件中的样式,是读取不到的
  • 可以通过getComputedStyle的全局函数来实现:

    var boxEl = document.querySelector(".box")
    console.log(boxEl.style.backgroundColor)
    // console.log(boxEl.style.fontSize)
    console.log(getComputedStyle(boxEl).fontSize)
    

6.5 dataset

HTML5的 data-* 自定义属性是可以在dataset属性中获取到的

<div id="abc" class="box" 
   data-age="18" data-height="1.88"></div>

<script>
var boxEl = document.querySelector(".box")
// 小程序开发中使用
console.log(boxEl.dataset.age)
console.log(boxEl.dataset.height)
</script>

七、元素操作

7.1 创建/插入/移除/克隆

  • document.createElement():创建元素

  • append:在 node 末尾 插入节点或字符串

  • prepend:在 node 开头 插入节点或字符串

  • before:在 node 前面 插入节点或字符串

  • after:在 node 后面 插入节点或字符串

  • replaceWith:将 node 替换 为给定的节点或字符串

  • remove:移除元素(自己)

  • cloneNode:克隆元素

    • 可以传入一个Boolean类型的值,来决定是否是深度克隆
    • 深度克隆会克隆对应元素的子元素

    image.png

    <body>
    
      <span>111111</span>
    
      <div class="box">
        <span class="box-first">呵呵呵呵</span>
        <p>哈哈哈哈哈</p>
      </div>
    
      <script>
        var boxEl = document.querySelector(".box")
        // 真实创建一个DOM对象
        var h2El = document.createElement("h2")
        h2El.className = "title"
        h2El.classList.add("active")
        h2El.textContent = "我是标题"
    
        // 将元素插入boxEl
        // boxEl.append(h2El)
        // boxEl.prepend(h2El)
        // boxEl.after(h2El)
        // boxEl.before(h2El)
        // boxEl.replaceWith(h2El, "abc")
    
        // 插入到span和p元素之间
        // var spanEl = document.querySelector("span") // 这个会拿成body下的第一个span
        
        // var spanEl = boxEl.children[0] // 直接拿boxEl的子元素
        var spanEl = boxEl.querySelector("span")
    
        spanEl.after(h2El)
    
      </script>
    </body>
    
      <body>
    
      <button class="remove-btn">移除box</button>
      <button class="clone-btn">复制box</button>
    
      <div class="box">
        <h2>我是标题</h2>
        <p>我是文本, 哈哈哈哈哈</p>
      </div>
    
      <script>
    
        // 1.获取元素
        var boxEl = document.querySelector(".box")
        var removeBtnEl = document.querySelector(".remove-btn")
        var cloneBtnEl = document.querySelector(".clone-btn")
    
        // 2.监听removeBtn的点击
        removeBtnEl.onclick = function() {
          boxEl.remove()
        }
    
        // 3.复制box
        var counter = 0
        cloneBtnEl.onclick = function() {
          var newNode = boxEl.cloneNode(true)
          newNode.children[0].textContent = "我是标题" + counter
          // boxEl.after(newNode)
          document.body.append(newNode)
    
          counter++
        }
      </script>
    </body>
    
  • 旧的操作方法:

    • parentElem.appendChild(node):在parentElem的父元素最后位置添加一个子元素
    • parentElem.insertBefore(node, nextSibling):在parentElem的nextSibling前面插入一个子元素
    • parentElem.replaceChild(node, oldChild):在parentElem中,新元素替换之前的oldChild元素
    • parentElem.removeChild(node):在parentElem中,移除某一个元素

7.2 元素大小/位置/滚动

  • 元素可视范围

    • clientWidth:contentWith+padding(不包含滚动条)
    • clientHeight:contentHeight+padding
    • clientTop:border-top的宽度
    • clientLeft:border-left的宽度
  • 元素完整

    • offsetWidth:元素完整的宽度
    • offsetHeight:元素完整的高度
    • offsetLeft:距离父元素的x
    • offsetHeight:距离父元素的y
  • 滚动

    • scrollHeight:整个可滚动的区域高度
    • scrollTop:滚动部分的高度
  • 补充

    • 当 clientHeight + scrollTop >= scrollHeight 时,表示已经抵达内容的底部了,可以加载更多内容 image.png
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        body {
          padding: 100px;
        }
    
        .box {
          width: 100px;
          height: 100px;
          padding: 20px;
          border: 10px solid red;
          /* box-sizing: border-box; */
          background-color: orange;
    
          overflow: auto;
        }
      </style>
    </head>
    <body>
    
      <div class="box">
        你去过国内最美的地方是哪# 我去过国内最美的地方是新疆喀纳斯。喀纳斯是一个美丽而神秘的地方,这里群山环抱,森林密布,湖水清澈,风景奇特。为国家级5A级景区,国家地质公园,国家森林公园。
      </div>
    
      <script>
        var boxEl = document.querySelector(".box")
    
        console.log(boxEl.clientWidth) // 123
        console.log(boxEl.clientHeight) // 140
    
        console.log(boxEl.clientLeft) // 10
        console.log(boxEl.clientTop) // 10
    
        console.log(boxEl.offsetWidth) // 160
        console.log(boxEl.offsetHeight) // 160
    
        console.log(boxEl.offsetLeft) // 108
        console.log(boxEl.offsetTop) // 108
    
        console.log(boxEl.scrollHeight) // 435
        console.log(boxEl.scrollTop) // 0
    
        // window对象
        window.onclick = function() {
          console.log(boxEl.scrollTop)
        }
    
      </script>
    </body>
    </html>
    

7.3 window大小/滚动

  • window的width和height

    • innerWidth、innerHeight:获取window窗口的宽度和高度(包含滚动条)
    • outerWidth、outerHeight:获取window窗口的整个宽度和高度(包括调试工具、工具栏)
    • documentElement.clientHeight、documentElement.clientWidth:获取html的宽度和高度(不包含滚动条)
  • window的滚动位置:

    • scrollX:X轴滚动的位置(别名pageXOffset)
    • scrollY:Y轴滚动的位置(别名pageYOffset)
  • 滚动到某位置的方法:

    • 方法 scrollBy(x,y) :将页面滚动至 相对于当前位置的 (x, y) 位置
    • 方法 scrollTo(pageX,pageY) 将页面滚动至 绝对坐标
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        .box {
          /* width: 2000px; */
          height: 100px;
          background-color: orange;
        }
    
        .scroll-btn {
          position: fixed;
          right: 20px;
          bottom: 20px;
          /* display: none; */
        }
      </style>
    </head>
    <body>
    
      <div class="box"></div>
      <button class="scroll-btn">回到顶部</button>
    
      <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
      <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
      <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
      <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
      <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
      <script>
        // window大小
        console.log(window.outerWidth)
        console.log(window.outerHeight)
    
        console.log(window.innerWidth)
        console.log(window.innerHeight)
    
        console.log(document.documentElement.offsetWidth)
        console.log(document.documentElement.offsetHeight)
    
        // 获取window的滚动区域
        window.onclick = function() {
          console.log(window.scrollX)
          console.log(window.scrollY)
        }
    
        var scrollBtnEl = document.querySelector(".scroll-btn")
        scrollBtnEl.hidden = true
        window.onscroll = function() {
          var scrollY = window.scrollY
          if (scrollY > 600) {
            // scrollBtnEl.style.display = "block"
            scrollBtnEl.hidden = false
          } else {
            // scrollBtnEl.style.display = "none"
            scrollBtnEl.hidden = true
          }
        }
    
        // 点击按钮后滚动到某个位置
        scrollBtnEl.onclick = function() {
          // window.scrollBy(0, 100)
          window.scrollTo(0, 0)
        }
    
      </script>
    </body>
    </html>