浏览器系列 — 原生 DOM 操作

前言

虽然现在是框架横行的时代,但在日常开发中避不开需要用到原生的 DOM 操作,看似简单,实际上在用的时候很多细节的地方还是要注意一下的,尤其是区别,这里做下笔记记录起来

原文地址:这些原生DOM操作你还记住多少

目录:

  • 常见 DOM 操作
    • 获取查找 DOM 元素
    • 面向 DOM 元素的增删改插复
    • 遍历 DOM 树上的元素
    • 给 DOM 元素设置样式(element.style)[本质上是设置内联样式]
    • 操作 DOM 元素上的属性
  • 获取浏览器、元素宽高汇总
    • 获取实际屏幕宽高(window.screen.weight / height)
    • 获取浏览器总宽高(window.outerWidth / outerHeight)
    • 获取当前窗口宽高(window.innerWidth / innerHeight)
    • 获取滚动后被隐藏页面的宽高(document.documentElement.scrollTop / scrollLeft)[也可认为是滚动条所处位置]
    • 获取元素布局宽高(element.offsetWidth / offsetHeight)[content + padding + border]
    • 获取元素内容宽高(element.scrollWidth / scrollWidth)[content + padding]
    • 获取元素距离顶部和左边距离(element.offsetTop / offsetLeft)
  • 浏览器原生事件
    • 鼠标事件
    • 键盘事件
    • 表单事件
    • window
    • 其他事件
  • Javascript原生对象
    • 时间对象 Date
    • Math 对象

常见 DOM 操作(基础)

获取指定的 DOM 元素

document.getElementById(idName)【没有加 s】

根据 idName 获取 DOM 元素,如果有相同 ID 也只能获取第一个(原则上 idName 不要重复)

image.png

document.getElementsByClassName(className)【有加 s】

获取相同 className 下的多个 DOM 元素,返回类数组结构

<div class="box">666</div>
<div class="box">666</div>
复制代码
console.log(document.getElementsByClassName("box"))
console.log(Array.from(document.getElementsByClassName("box")))
复制代码

image.png

类数组结构的原型是一个 HTMLCollection 对象;转化为数组对象后其原型变为 Array(0),就能使用数组的所有方法了;区别就在于这里。

document.getElementsByTagName(tagName)【有加 s】

获取相同 tagName 下的多个 DOM 元素,返回类数组结构

document.querySelector(selectors) | document.querySelectorAll(selectors)

selectors 的写法跟 CSS 选择器的写法一致。这两个是唯一支持使用选择器来查找元素的api,有个这个api我们在进行 深层次查找的时候方便很多

querySelector 获取单个元素,querySelectorAll 获取多个元素返回类数组结构

<div class="warp">
    <p>name</p>
    <p>age</p>
</div>
复制代码

目标:要获取 wrap 元素下的所有 p 元素

1. 不使用 querySelectorAll
const warp = document.getElementsByClassName("warp")[0];
const allp = warp.getElementsByTagName(p)

2. 使用 querySelectorAll

const allp = document.querySelectorAll(".warp p")
复制代码

image.png

另外的区别还在于:使用 querySelectorAll 方法获取的元素可以使用 keys()、values()、entires()、forEach()、item() 等方法

image.png

注意:后面所有的 element 代表获取 DOM 元素后所赋值的变量

DOM 元素的增删改插复

创建 DOM 元素

const p = document.createElement("p");
复制代码

删除 DOM 元素

element.remove(); // 删除 element

parentEle.removeChild(clildEle) // 删除 element 中的子元素 childEle
复制代码

替换 DOM 元素

parentEle.replaceChild(newEle,oldEle)
复制代码
  <body>
    <div class="box">
      <h1>oldEle</h1>
    </div>
    <button id="btn">变换</button>
    
    <script>
      const btn = document.getElementById("btn");
      const box = document.getElementsByClassName("box")[0];
      const h1 = document.getElementsByTagName("h1")[0];
      const h2 = document.createElement("h2");
      h2.innerText = "newEle";
      btn.onclick = function () {
        box.replaceChild(h2, h1); // 成功把节点 h1 替换成节点 h2
      };
    </script>
  </body>
复制代码

插入 DOM 元素

parentEle.appendChild(childEle2) // 在 parentEle 的最后插入 childEle

parentEle.insertBefore(childEle2,childEle1) // 在 parentEle 元素中的 childEle1 元素前插入 childEle2
复制代码

拷贝 DOM 元素

const element2 = element1.cloneNode( true | false )
// true 表示进行深拷贝,如果 element1 里面有子节点也拷贝过来
// false 表示进行浅拷贝,单拷贝 element1 节点
复制代码

遍历 DOM 元素

  • childElementCount:返回子元素的个数,不包括文本节点和注释
  • firstElementChild:返回第一个子元素
  • lastElementChild:返回最后一个子元素
  • previousElementSibling:返回前一个相邻兄弟元素
  • nextElementSibling:返回后一个相邻兄弟元素

————————————————————————————————

  • parentNode:查找指定节点的父节点
  • firstChild:查找指定节点的第一个字节点
  • lastChild:查找指定节点的最后一个字节点
  • nextSibling:查找指定节点的下一个节点
  • previousSibling:查找指定节点的上一个节点

注意区分 节点 和 元素 之间的区别:

<body>
    <div id="box">666<p>文件</p></div>

    <script>
      const box = document.getElementById("box");
      console.log(box.firstChild); // 打印 text节点 "666"
      console.log(box.firstElementChild); // 打印 p 标签
    </script>
 </body>
复制代码

给 DOM 节点设置样式

语法:element.style

<style>
    element选择器 {
        width: 30px
    }
</style>
<script>
    element.style.width = 50px // 设置后该元素的宽度由 30px 变为 50px
</script>
复制代码

操作 DOM 的属性

// 获取属性的值
Ele.getAttribute("data-id");
// 新增属性
Ele.setAttribute("data-id", 1);
// 删除属性
Ele.removeAttribute("data-id");
复制代码

获取浏览器、元素宽高汇总

获取实际屏幕宽高

const W  =  window.screen.width 
const H  =  window.screen.height
复制代码

获取浏览器宽高

const W  =  window.outerWidth 
const H  =  window.outerHeight
复制代码

image.png

获取当前窗口宽高(浏览器视口宽高)

const W  =  window.screen.width 
const H  =  window.screen.height
复制代码

image.png

获取滚动后被隐藏页面的宽高(滚动条所处位置)

const H = document.documentElement.scrollTop;
const W = document.documentElement.scrollLeft
复制代码

获取元素 布局 宽高

const W = element.offsetWidth;
const H = element.offsetHeight;
复制代码

获取元素 内容 宽高

const W = element.scrollWidth;
const H = element.scrollHeight;
复制代码

示例(对比以上两种方式的区别)

<html>
<head>
    <style>
        #box{
          width: 100px;
          height: 100px;
          padding: 30px;
          border: 20px solid black;
        }
    </style>
</head>
<body>
    <div id="box">666</div>
    <script>
        var element = document.getElementById("box")
        console.log(element.offsetWidth,element.offsetHeight) // 100 + (20 + 30) * 2 == 200
        console.log(element.scrollWidth,element.scrollHeight) // 100 + 30 * 2 == 160
    </script>
</body>
</html>
复制代码

image.png

  • element.offsetWidth 和 element.offsetHeight 包括 content、padding、border
  • element.scrollWidth 和 element.scrollHeight 只包括 content、padding

获取元素距离顶部和左边距离

const top = element.offsetTop;
const left = element.offsetLeft;
复制代码

image.png

浏览器原生事件

使用这些方法前记得前面要写对象,要么是 document,要么是具体的 DOM 元素

鼠标事件

事件集合

  • onclick:单击事件
  • ondblclick:双击事件
  • oncontextmenu:右击事件
  • onmousedown:鼠标按下事件(包括按下状态)
  • onmousemove:鼠标移动事件
  • onmouseup:鼠标按键松开事件
  • onmouseover:鼠标移动进入到元素上(包括其子元素)
  • onmouseout:鼠标移动离开到元素上(包括其子元素)
  • onmouseenter:鼠标移动进入到元素上(不包括其子元素)
  • onmouseleave:鼠标移动离开到元素上(不包括其子元素)

事件 event 的值

鼠标事件发生时的 event 是一个 MouseEvent 对象,其中比较常用的属性有:

  • “screenX”:鼠标事件发生时相对于用户屏幕的水平坐标位置;该操作并不会改变真实鼠标的位置。
  • “screenY”:鼠标事件发生时相对于用户屏幕的垂直坐标位置;该操作并不会改变真实鼠标的位置。
  • “clientX”:鼠标事件发生时相对于客户端窗口的水平坐标位置;该操作并不会改变真实鼠标的位置。
  • “clientY”:鼠标事件发生时相对于客户端窗口的垂直坐标位置;该操作并不会改变真实鼠标的位置。

示例

  • 基于鼠标事件完成拖拽
  const box = document.getElementById("box");
  let nowW, nowH, flag;
  box.onmousedown = function (e) {
    nowW = e.clientX;
    nowH = e.clientY;
    flag = true;
    document.onmousemove = function (e) {
      if (!flag) return false;
      const moveX = e.clientX - nowW;
      const moveY = e.clientY - nowH;
      const left = parseInt(box.style.left || 0);
      const top = parseInt(box.style.top || 0);
      box.style.left = left + moveX + "px";
      box.style.top = top + moveY + "px";
      nowW = e.clientX;
      nowH = e.clientY;
    };
    document.onmouseup = function () {
      flag = false;
    };
    document.onmouseleave = function () {
      flag = false;
    };
  };
复制代码

效果:

  • 基于鼠标事件完成自定义右键
  <body>
    <div id="box"></div>
    <div id="option">
      <div class="item">复制</div>
      <div class="item">放大</div>
      <div class="item">搜索</div>
    </div>
    <script>
      const box = document.getElementById("box");
      const option = document.getElementById("option");
      box.oncontextmenu = function (e) {
        const x = e.clientX;
        const y = e.clientY;
        option.style.display = "block";
        option.style.top = y + "px";
        option.style.left = x + "px";
        return false;
      };
      option.onclick = function () {
        this.style.display = "none";
      };
    </script>
  </body>
复制代码

效果:

键盘事件

使用这些方法的固定格式为:

document.addEventListener("事件名称", function () {
    // 代码
})
复制代码

事件集合

  • keydown:当用户按下键盘上的任意键时触发,而且如果按住按住不放的话,会重复触发此事件
  • keypress:当用户按下键盘上的字符键时触发(就是说用户按了一个能在屏幕上输出字符的按键keypress事件才会触发),而且如果按住不放的,会重复触发此事件(按下Esc键也会触发这个事件)
  • keyup:当用户释放键盘上的键时触发
  • 判断按的是哪个键:根据 e.keyCode 的键值去判断

示例

  • 基于键盘事件完成使用方向键移动div
  <body>
    <div id="box">
      <div id="move">静止</div>
    </div>
    <script>
      const box = document.getElementById("box");
      const move = document.getElementById("move");
      let lefts = box.style.left || 0;
      let tops = box.style.top || 0;
      document.addEventListener("keydown", function (e) {
        const code = e.keyCode;
        move.innerHTML = "开始移动";
        switch (code) {
          case 38:
            move.innerHTML = "上";
            tops -= 5;
            break;
          case 40:
            move.innerHTML = "下";
            tops += 5;
            break;
          case 37:
            move.innerHTML = "左";
            lefts -= 5;
            break;
          case 39:
            move.innerHTML = "右";
            lefts += 5;
            break;
          default:
            break;
        }

        box.style.top = tops + "px";
        box.style.left = lefts + "px";
      });
      document.addEventListener("keyup", function () {
        move.innerHTML = "静止";
      });
      document.addEventListener("keypress", function () {
        console.log("keypress");
      });
    </script>
  </body>
复制代码

效果:

表单事件

  • submit:表单提交
  • reset:表单重置
  • change:值发生改变
  • blur:离焦(不会冒泡)
  • focus:聚焦(不会冒泡)

window

window 事件指的是浏览器窗口本身而不是窗口内的文档对象。

  • onload:当文档和资源加载完成后调用
  • unload:当用户离开当前文档转而其他文档时调用
  • resize:浏览器窗口改变

其他事件

  • beforeunload:关闭浏览器窗口之前触发的事件
  • DOMContentLoaded:文档对象加载完成之后就触发的事件,无需等待样式、图片等资源
  • window.onload:文档和资源均加载完毕
  • document.DOMContentLoaded:文档加载完毕,资源未定加载完毕
  • pageShow 和 pagehide:每次用户浏览关闭页面时触发
  • readystatechange:document有 readyState 属性来描述 document 的 loading状态,readyState 的改变会触发 readystatechange 事件
  • document.readyState === ‘complete’ 页面已加载完毕
  • document.readyState === ‘loading’ 页面正在加载

Javascript原生对象

Date 对象

事件集合

  • toLocaleDateString():根据本地时间格式,把Date对象的日期部分转化为字符串
  • toLocaleTimeString():根据本地时间格式,把Date对象的时间部分转化为字符串
  • toLocaleString():根据本地时间格式,把Date对象转化为字符串
  • getTime():获取当前时间戳

  • 时间戳转换为时间
      function timestampToTime(timestamp) {
        if (typeof timestamp != "number") return false;
        if (timestamp.length === 10) timestamp = timestamp * 1000;
        const date = new Date(timestamp);
        Y = date.getFullYear() + "-";
        M =
          (date.getMonth() + 1 < 10
            ? "0" + (date.getMonth() + 1)
            : date.getMonth() + 1) + "-";
        D = (date.getDate() < 9 ? "0" + date.getDate() : date.getDate()) + " ";
        h =
          (date.getHours() < 9 ? "0" + date.getHours() : date.getHours()) + ":";
        m =
          (date.getMinutes() < 9
            ? "0" + date.getMinutes()
            : date.getMinutes()) + ":";

s = date.getSeconds() < 9 ? "0" + date.getSeconds() : date.getSeconds();
        return Y + M + D + h + m + s;
      }
复制代码
  • 时间转化为时间戳
  function timeToTimestamp(time){
    const date = new Date(time);
    return date.getTime()
  }
复制代码

Math 对象

// 取绝对值
Math.abs(-1)  // 1
// 向上取整
Math.ceil(1.1)  // 2
// 向下取整
Math.floor(1.1)  // 1
// 四舍五入
Math.round(1.5)  // 2
// 取最大值
Math.max(123)  // 3
// 取最小值
Math.min(123)  // 1
// 产生0-1的随机数
Math.random() 
// 次方
Math.pow(2,3)  // == 2*2*2 == 8
// 平方根
Math.sqrt(36)  // 6
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享