前言
虽然现在是框架横行的时代,但在日常开发中避不开需要用到原生的 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 不要重复)
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")))
复制代码
类数组结构的原型是一个 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")
复制代码
另外的区别还在于:使用 querySelectorAll 方法获取的元素可以使用 keys()、values()、entires()、forEach()、item() 等方法
注意:后面所有的 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
复制代码
获取当前窗口宽高(浏览器视口宽高)
const W = window.screen.width
const H = window.screen.height
复制代码
获取滚动后被隐藏页面的宽高(滚动条所处位置)
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>
复制代码
- element.offsetWidth 和 element.offsetHeight 包括 content、padding、border
- element.scrollWidth 和 element.scrollHeight 只包括 content、padding
获取元素距离顶部和左边距离
const top = element.offsetTop;
const left = element.offsetLeft;
复制代码
浏览器原生事件
使用这些方法前记得前面要写对象,要么是 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(1,2,3) // 3
// 取最小值
Math.min(1,2,3) // 1
// 产生0-1的随机数
Math.random()
// 次方
Math.pow(2,3) // == 2*2*2 == 8
// 平方根
Math.sqrt(36) // 6
复制代码