JS DOM操作
什么是DOM?#
文档对象模型(Document Object Model),是 W3C 组织推荐的处理可拓展标记语言(HTML或者XML)的编程接口。
W3C 已经定义了一系列的 DOM 接口,通过这些接口可以改变网页的内容、结构和样式。
DOM 树#
- 文档:一个页面就是一个文档,DOM 中使用 document 表示
- 元素:页面中的所有标签都是元素,DOM中使用 element 表示
- 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示
DOM 把以上内容都看成是对象
获取元素#
代码 | 归属 | 描述 |
---|---|---|
document.getElementById(‘nav’) | DOM 老方法不推荐 | 通过元素的 id 属性值获取元素,只返回第一个元素 |
document.getElementByTagName(‘div’) | DOM 老方法不推荐 | 通过元素的标签名获取元素,将选择到的所有对象存入伪数组并返回 |
document.querySelector(‘.nav li’) | H5 新增方法推荐 | 通过选择器的方法获取元素,只返回第一个对象 |
document.querySelectorAll(‘.nav li’) | H5 新增方法推荐 | 通过选择器的方法获取元素,将选择到的所有对象存入伪数组并返回 |
document.getElementByClassName(‘nav’) | H5 新增方法 | 通过元素的类名获取元素,将选择到的所有对象存入伪数组并返回,不兼容ie |
document.body | 获取整个文档的body部分 | |
document.documentElement | 获取整个文档,即html部分 |
根据元素 ID 获取 getElementById()#
-
此方法为 DOM 老 API,兼容性好,但是不推荐开发时使用。
-
此方法只返回获取到的第一个元素对象。
-
语法:
// 获取 id 为 time 的第一个元素
var timer = document.getElementById('time');
// 返回获取到的整个元素标签
console.log(timer);
// 返回获取到的元素类型
console.log(typeof timer);
// 在控制台中显示指定 JavaScript 对象的属性,并通过类似文件树样式的交互列表显示, 更好的查看属性和方法
console.dir(timer);
通过标签名获取 getElementByTagName()#
-
此方法为 DOM 老 API,兼容性好,但是不推荐开发时使用。
-
此方法将获取到的对象存放于伪数组,以伪数组的形式返回所有获取的元素。
-
如果获取到的元素只有一个,依然返回伪数组;如果没有获取到元素,返回的是一个空的伪数组、
-
语法:
// 获取页面中所有 li
var lis = document.getElementsByTagName('li');
// 输出伪数组
console.log(lis);
// 输出伪数组中的第2个对象
console.log(lis[1]);
// 遍历
for (i = 0; i < lis.length; i++){
console.log(lis[i]);
}
根据类名来获取 getElementByClassName()#
- 此方法为 HTML5 新增的方法,仅仅兼容ie9+,平时不常用。
- 此方法将获取到的对象存放于伪数组,以伪数组的形式返回所有获取的元素。
- 如果获取到的元素只有一个,依然返回伪数组;如果没有获取到元素,返回的是一个空的伪数组。
- 语法:
var box = document.getElementsByClassName('box');
console.log(box);
根据选择器获取 querySelector()#
- 此方法为 HTML5 新增的方法,仅仅兼容ie9+,推荐使用。
- 此方法只返回获取到的第一个元素对象。
var box = document.querySelector('.box');
console.log(box);
根据选择器获取 querySelectorAll()#
- 此方法为 HTML5 新增的方法,仅仅兼容ie9+,推荐使用。
- 此方法将获取到的对象存放于伪数组,以伪数组的形式返回所有获取的元素。
- 如果获取到的元素只有一个,依然返回伪数组;如果没有获取到元素,返回的是一个空的伪数组
var box = document.querySelectorAll('.box');
console.log(box);
获取 body 和 html#
- 在文档中元素的获取中,有专门获取 body 和 html 的方法
- 语法:
// 获取body
var body = document.body;
console.log(body);
console.dir(body);
// 获取整个html
var htmlEle = document.documentElement;
console.log(htmlEle);
事件操作#
网页中的每个元素都可以产生某些可以触发 JS 的事件,例如,我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作
事件有三部分组成:事件源、事件类型、事件处理程序,我们将其称为事件三要素
- 事件源:事件的触发对象(谁触发了事件?)
- 事件类型:事件如何被触发 什么事件 比如鼠标点击(onclick)还是鼠标经过 还是键盘按下
- 事件处理程序:事件被触发要执行的操作
注册事件#
给元素添加事件,称为注册事件或者绑定事件。
注册事件有两种方式:传统方式和方法监听注册方式。
-
传统注册方式
-
使用 on 开头的事件 onclick
-
<button onclick="alert('hi')"></button>
-
btn.onclock = function(){}
-
特点:注册事件的唯一性
-
同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数。
-
-
监听注册方式
-
w3c 标准 推荐方式
-
addEventListener() 他是一个方法
-
IE9之前的IE版本不支持此方法,可以使用attachEvent() 代替
-
特点:同一个元素同一个事件可以注册多个监听器
-
传统方式注册事件#
事件 | 描述 |
---|---|
onclick | 点击事件 |
onfocus | 获得焦点事件 |
onblur | 失去焦点事件 |
onmouseover | 鼠标经过 |
onmouseout | 鼠标离开 |
onmousemove | 鼠标移动 |
onmouseup | 鼠标弹起 |
onmousedown | 鼠标按下 |
语法:
// 获取按钮元素
var btn = document.querySelector('button');
// 给按钮元素添加点击事件
btn.onclick = function(){
// 事件处理程序,但被点击时执行
console.log('按钮被点击');
}
addEventListener 事件监听方式#
eventTarget.addEventListener(type, listener, useCapture)
eventTarget.addEventListener() 方法将指定的监听器注册到 evenTarget (目标对象) 上,当该对象触发指定事件时,就会执行事件处理函数。
该方法有三个参数:
- type:事件类型字符串,比如 click、mouseover,注意这里并没有on
- listener:事件处理函数,事件发生时,会调用该监听函数
- useCapture:事件流,默认为false。flase为冒泡阶段,true为捕获阶段。
代码实例:
// 给元素btn添加两个监听鼠标点击事件
btn.addEvenListener('click',function(){
alert(22);
})
btn.addEvenListener('click',function(){
alert(33);
})
attachEvent 事件监听方式#
eventTarget.attachEvent(type, callback)
该方法将指定的监听器注册到指定的对象上,当对象被触发,就会执行指定的回调函数。
该方法只支持ie9之前的ie浏览器,并不被其他浏览器支持。
- type:事件类型字符串,比如 onclick、onmouseover,这里要带有 on
- callback:事件处理函数,当目标触发事件时回调函数被调用
代码实例:
btn.attachEvent('onclick', function(){
alert(11)
})
对不同浏览器的兼容性处理#
这里写一个兼容性函数,来适配不同浏览器的兼容性问题(PS:IE就是个毒瘤)
兼容性要首先照顾大多数浏览器,再处理特殊浏览器
function addEventListener(element, eventName, fn){
// 判断当前浏览器是否支持 addEventListener
if(element.addEvenListener){
element.addEventListener(eventName, fn);
}else if(element.attachEvent){
element.attachEvent('on' + eventName, fn);
}else{
// 相当于 element.onclick = fn
element['on' + eventName] = fn;
}
}
删除事件(解绑事件)#
传统方式删除事件#
直接给指定的对象的相应的事件赋值为null,即可删除该事件。
eventTarget.onclick = null;
监听方式删除事件 removeEventListener#
eventTarget.removeEventListener(type, listener, useCapture)
-
type:事件类型字符串,比如 click、mouseover,注意这里并没有on
-
listener:需要解绑的事件处理函数
-
useCapture:事件流,默认为false。flase为冒泡阶段,true为捕获阶段。
代码实例:
btn.addEventListener('click', fn);
function fn() {
alert(22);
btn.removeEventListener('click', fn);
}
注意:如果要删除监听事件,那么添加监听事件时一定要用具体的函数名,不能使用匿名函数。使用匿名函数时,再删除事件时候,无法指定事件触发函数。
监听方式删除事件 detachEvent#
此方法对应 attackEvent
eventTarget.detachEvent(type, callback)
- type:事件类型字符串,比如 onclick、onmouseover,这里要带有 on
- callback:要删除的事件处理函数
代码实例:
btn.attachEvent('onclick', fn);
function fn() {
alert(33);
btn.detachEvent('onclick', fn);
}
对不同浏览器的兼容性处理#
function removeEventListener(element, eventName, fn){
// 判断当前浏览器是否支持 removeEventListener
if(element.removeEvenListener){
element.removeEventListener(eventName, fn);
}else if(element.detachEvent){
element.detachEvent('on' + eventName, fn);
}else{
// 相当于 element.onclick = fn
element['on' + eventName] = null;
}
}
DOM 事件流#
事件流描述的是从页面接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程称为 DOM 事件流。
DOM 事件流分为3个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
事件冒泡:IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到 DOM 最顶层节点的过程。
事件捕获:网景最早提出,由 DOM 最顶层节点开始,然后逐级向下传播到最具体的元素接收的过程。
代码验证#
- JS 代码只能执行捕获或者冒泡的其中一个阶段。
- onclick 和 attachEvent 只能得到冒泡阶段。
- addEventListener中的第三个参数如果是 true,表示再事件捕获阶段调用事件处理程序;如果是false(不写默认时false)则表示再事件冒泡阶段调用事件处理程序。
<!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>事件流</title>
<style>
.father {
width: 300px;
height: 300px;
margin: 10px auto;
background-color: antiquewhite;
overflow: hidden;
}
.son {
width: 200px;
height: 200px;
margin: 50px auto;
background-color: aliceblue;
}
</style>
</head>
<body>
<div class="father">father
<div class="son">
son 冒泡阶段 触发事件处理程序
</div>
</div>
<div class="father">father2
<div class="son">
son2 捕获阶段 触发事件处理程序
</div>
</div>
<script>
var son = document.querySelectorAll('.son');
// 指定事件在冒泡阶段触发事件处理程序
son[0].addEventListener('click', function () {
alert('son');
})
son[0].parentNode.addEventListener('click', function () {
alert('fatehr');
})
// 指定事件在捕获阶段触发事件处理程序
son[1].addEventListener('click', function () {
alert('son');
}, true)
son[1].parentNode.addEventListener('click', function () {
alert('fatehr');
}, true)
</script>
</body>
</html>
事件对象#
事件对象只有有了事件才会存在,他是系统给我们自动创建的,不需要我们传递参数。
事件对象是我们事件的一系列的相关数据的集合,跟事件相关的,比如鼠标点击里面就包含了鼠标的相关信息,如鼠标坐标等。如果是键盘事件,那么里面就包含的键盘事件的信息,比如判断用户按下了哪个键。
事件对象可以由我们自己命名,比如 event、evt、e。
对 ie678 有兼容性问题,ie678 不可自己对事件对象命名,只能使用window.event
代码:
div.onclick = function(event) {
console.log(event);
}
兼容性处理:
div.onclick = function(e) {
e = e || window.event;
console.log(e);
}
常见事件对象的属性和方法#
属性 | 描述 |
---|---|
e.target | 返回触发事件的对象 不兼容ie678 |
this | 返回的是绑定事件的对象 |
e.srcElement | 返回触发事件的对象 兼容ie678 |
e.currentTarget | 和this相似 但是不兼容ie678 |
e.type | 返回事件的类型,比如 click、mouseover 不带on |
e.cancelBubbel | 阻止冒泡 ie678不兼容 |
e.returnValue | 阻止默认事件(默认行为)非标准 比如不让链接跳转 ie678不兼容 |
e.preventDefault() | 阻止默认事件(默认行为)标准 |
e.stopPropagation() | 阻止冒泡 标准 |
this 和 target#
如果我们有一个 ul>li,给 ul 绑定一个点击事件。
那么当我们点击 li 的时候:
e.target 返回的是触发事件的对象,也就是 li,e.target 不兼容ie678
this 返回的是绑定事件的对象,也就是 ul
对于这两个方法我们还有两个额外的相似的方法:
e.srcElement 对应 e.target,但是前者兼容了 ie678
e.currentTarget 对应 this,但是前者不兼容ie678
阻止默认行为#
有些标签默认就带有一些行为,比如 a 链接跳转等,我们可以使用如下方法阻止其默认行为。
阻止行为的方法有两种:
- e.preventDefault():标准的阻止默认事件方法,推荐使用,但是不兼容ie678
- e.returnValue:这是一个属性,兼容ie678。
- return false:这种方法也可以阻止默认事件,而且没有兼容性问题。需要注意的是,用这种方法后,return之后的代码将不会执行。
a.onclick = function(e) {
e.preventDefault();
e.returnValue;
return false;
}
阻止冒泡(重点)#
我们已经知道 dom 事件流包括:捕获,目标,冒泡三个阶段。
事件开始冒泡时,事件将会由具体的目标元素向上逐级传递到dom最顶层节点。
阻止冒泡就是阻止事件向上传播。
阻止冒泡的方法有两种:
- e.stopPropagation():标准阻止冒泡的方法,推荐使用,但是不兼容ie678
- e.cancelBubbel:这是一个属性,用于阻止冒泡,兼容ie678
div.onclick = function(e) {
e.stopPropagation();
e.cancelBubbel = True;
}
事件委托#
事件委托也称为事件代理,在jQuery里面也叫事件委派。
其思想就是,当一个父节点中的所有子节点都需要点击事件时,我们不是给每个子节点单独设置事件监听器,而是将事件监听器设置到父亲节点上,然后利用冒泡原理来影响每个子节点,这样点击子节点就可以触发父节点的监听器。
这样我们只需要操作一次DOM,提高了程序的性能。
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
e.target.style.backgroundColor = 'pink';
})
</script>
</body>
常用的鼠标事件#
禁止鼠标右键菜单(contextmenu)#
contextmenu 主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单。
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
禁止鼠标选中(selectstart 开始选中)#
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
鼠标事件对象#
event 对象代表了事件的状态,跟事件相关的一些列信息的集合。其中就包裹键盘事件信息和鼠标事件信息。鼠标事件对象是 MouseEvent;键盘事件对象是 KeyboardEvent。
鼠标事件对象 | 描述 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的 X 坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的 Y 坐标 |
e.pageX | 返回鼠标相对于文档页面的 X 坐标 IE9+支持 |
e.pageY | 返回鼠标相对于文档页面的 Y 坐标 IE9+支持 |
e.screenX | 返回鼠标相对于电脑屏幕的 X 坐标 |
e.screenY | 返回鼠标相对于电脑屏幕·的 Y 坐标 |
常用的键盘事件#
键盘事件 | 描述 |
---|---|
onkeyup | 某个键盘按键被松开时触发 |
onkeydown | 某个键盘按键被按下时触发 |
onkeypress | 某个键盘按键被按下时触发 但是这个方法不识别功能键,比如 ctrl shift等 |
当三个事件同时存在时,执行顺序永远为:keydown --> keypress --> keyup
键盘事件对象#
事件对象 | 描述 |
---|---|
key | 记录用户按下的键盘按键,除了ie678,还有些其他浏览器不兼容 |
keyCode | 记录用户按下键的 ASCLL 值 |
操作元素#
JavaScript 的 DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内容、属性等。
改变元素内容#
innerText#
- innerText 只获取元素中的文本内容
- innerText 会删除空格和换行,只保留文本
语法:
var div = document.querySelector('div');
div.innerText = 'brokyz'
innerHTML#
- innerHTML 会保留空格和换行
- innerHTML 修改时支持 HTML 标签,在内容中添加标签将会被识别
- 推荐使用 innerHTML
var div = document.querySelector('div');
div.innerHTML = '<strong>brokyz</strong>'
修改或添加属性内容#
- 当获取到元素时,我们对元素中的属性进行添加和更改。
- 本方法对 html 中已经有定义的属性进行操作。
- 修改属性时会直接覆盖掉原来的属性值。
语法:
// 获取a标签
var a = document.querySelector('a');
// 更改或添加a的属性
a.href = 'https://bilibili.com';
a.id = 'bilibili';
// 修改类名属性值
a.className = 'iama';
表单元素的属性操作#
利用 DOM 可以操作如下表单元素属性:
type、value、checked、selected、disabled
修改或添加CSS样式属性#
- 我们可以通过 JS 修改元素的大小、颜色、位置等 CSS 样式。
- JS 里面的样式采用驼峰命名法,比如 fontSize、backgroundColor
- JS 修改 style 样式操作,产生的是行内样式,修改后的 CSS 权重更高
语法:
var div = document.querySelector('div');
this.style.backgroundColor = 'antiquewhite';
this.style.width = '400px';
使用 className 修改元素类名的方式修改CSS样式属性#
- 使用 className 修改样式属性会直接覆盖掉原来的 class 值
<!DOCTYPE html>
<head>
<style>
.text {
width: 400px;
height: 400px;
background-color: antiquewhite;
}
.change {
background-color: aliceblue;
}
</style>
</head>
<body>
<div class=”text“>文本</div>
<script>
var div = document.querySelector('div');
div.onclick = function(){
// 此方法会直接覆盖掉原来class属性中的text
this.className = 'change';
// 如果不覆盖原来的class属性,只是追加的话可以这样使用
this.className += ' change';
}
</script>
</body>
</html>
对自定义属性值的操作#
- 在标签中,有些属性是内置的,比如 a标签的
href
、target
等,这些都可以直接获取元素a,然后使用a.href
对属性进行操作。 - 在标签中,也有些属性是我们自定义的,比如我们自己给a标签定义一个
index = '1'
,这时我们就不能使用a.index
对自定义属性进行操作。 - 以下我们将讲解对自定义属性的操作方法:
获取自定义属性值 getAttribute()#
getAttribute()
既可以获取自定义的属性值,也可以获取自带的属性值。
语法:
var div = document.querySelector('div');
// 获取内置属性值
console.log(div.getAttribute('id'));
// 获取自定义属性值
console.log(div.getAttribute('index'));
添加和修改自定义属性值#
div.setAttribute('自定义属性','要修改的值');
既可以修改自定义的属性值,也可以修改自带的属性值。- 但是用
div.setAttribute('自定义属性','要修改的值')
修改元素的类名时,只需要指定class
即可,不需要自带方法那样使用className
语法:
var div = document.querySelector('div');
div.setAttribute('index','2');
div.setAttribute('class','box');
- 当使用
setAttribute
设置 class 时就是使用 class 而不是使用 className
移除自定义属性值#
div.removeAttribute()
既可以删除自定义的属性值,也可以删除自带的属性值。
语法:
div.removeAttribute('index');
H5自定义属性新规范#
由于自定义属性,无法使用自带的方法div.index
调用,所以html5新增了对自定义属性的调用支持
- h5标准要求在自定义属性前加
data-
,当调用的时候使用dataset
调用 - 当自定义属性中有多个 - 连接时,调用时需要使用驼峰命名法调用
- 此方法存在兼容性问题,使用 dataset 获取时,仅对ie11+支持
语法:
<body>
<div data-listname="123" data-list-name="456"></div>
<script>
var div = document.querySelector('div');
console.log(div.dataset.listname);
console.log(div.dataset.listName);
</script>
</body>
节点操作#
节点操作可以利用层级关系获取元素,为我们开发提供了一种更加方便的获取元素的方法。
节点概述#
网页中的所有内容都是节点(标签、属性、文本、注释等),在 DOM 中,节点使用 node 来表示。
HTML DOM树中的所有节点均可以通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。
一般地,节点至少拥有node Type(节点类型)、nodeName(节点名称)和 nodeValue(节点值)这三个基本属性。
- 元素节点 nodeType 为 1
- 属性节点 nodeType 为 2
- 文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)
实际开发中,节点操作主要操作的是元素节点
节点的使用#
代码 | 使用频率 | 描述 |
---|---|---|
ul.parentNode | 常用 | 获取父亲节点,如果找不到返回空 |
ul.childNodes | 不常用 | 得到所有子节点,包含 元素节点 文本节点等等 |
ul.children | 常用 | 获取所有的子元素节点 实际开发常用 |
ul.firstChild | 不常用 | 获取第一个子节点,不管是文本节点和元素节点都可以被拿到 |
ul.lastChild | 不常用 | 获取最后一个子节点,不管是文本节点和元素节点都可以被拿到 |
ul.firstElementChild | 常用 | 获取第一个元素节点,仅支持ie9+ |
ul.lastElementChild | 常用 | 获取最后一个元素节点,仅支持ie9+ |
li.nextSibling | 不常用 | 返回下一个兄弟节点 包含 元素节点 文本节点等等 |
ul.nextElementSibling | 常用 | 返回下一个元素兄弟节点,仅支持ie9+ |
ul.previousSibling | 不常用 | 返回上一个兄弟节点 包含 元素节点 文本节点等等 |
ul.previousElementSibling | 常用 | 返回上一个元素兄弟节点,仅支持ie9+ |
// 1.父节点 parentNode
var erweima = document.querySelector('.erweima');
console.log(erweima.parentNode); // 如果找不到父节点就返回为空
// 2.子节点 childNodes (集合) 得到所有子节点,包含 元素节点 文本节点等等
var ul = document.querySelector('ul');
console.log(ul.childNodes);
// 注意:返回值里面包含了所有的子节点
// 如果只想获得里面的元素节点,则需要专门处理。所以我们一般不提倡使用childNodes
for (let i = 0; i < ul.childNodes.length; i++) {
const element = ul.childNodes[i];
if (element.nodeType == 1){
console.log(element);
}
}
// children 获取所有的子元素节点 实际开发常用
console.log(ul.children);
// firstchild 获取第一个子节点,不管是文本节点和元素节点都可以被拿到
console.log(ul.firstChild);
// lastchild 获取最后一个子节点,不管是文本节点和元素节点都可以被拿到
console.log(ul.lastChild);
// firstElementChild 获取第一个元素节点
console.log(ul.firstElementChild);
// lastElementChild 获取最后一个元素节点
console.log(ul.lastElementChild);
// 注意:这几个返回第一个和最后一个存在兼容性问题,不支持ie9
// 实际开发中,兼顾兼容性
console.log(ul.children[0]);
// 3.兄弟节点
// nextSibling 返回下一个兄弟节点 包含 元素节点 文本节点等等
console.log(ul.nextSibling);
// nextElement 返回下一个元素兄弟节点
console.log(ul.nextElementSibling);
// prevousSibling 返回上一个兄弟节点 包含 元素节点 文本节点等等
console.log(ul.previousSibling);
// prevousElementSibling 返回上一个兄弟节点 包含 元素节点 文本节点等等
console.log(ul.previousElementSibling);
创建节点并添加节点#
代码 | 描述 |
---|---|
ul.appendChild() | 在孩子的最后面添加元素 |
ul.insertBefore(要添加的元素,指定的孩子元素) | 在指定孩子元素的前面添加要添加的元素 |
语法:
var li = document.createElement('li');
var ul = document.querySelector('ul');
// 在ul的孩子后面追加元素
ul.appendChild(li);
// 在ul的指定孩子前面插入元素
ul.insertBefore(li,ul.children[0])
删除节点#
var ul = document.querySelector('ul');
// 删除父节点里面的孩子
ul.removeChild(ul.children[0]); // 删除ul中的第一个孩子
复制节点#
var ul = document.querySelector('ul');
//复制节点
var cloned = ul.children[0].cloneNode(true); //括号为空或者false,是浅拷贝, 则只复制标签不复制内容,如果为true,复制内容,深拷贝
ul.appendChild(cloned);
三种创建元素方式的区别#
-
document.write()
document.write('<div>123<div>')
文档执行完毕,他会导致页面全部重绘
-
innerHTML = ‘ ’
div.innerHTML += '<div>123<div>'
使用拼接的方式创建多个元素时,耗时非常大- 当将要创建的元素插入数组中,再通过innerHTML插入时,效率大大提成,为最优
-
document.createElement()
- 使用这种方法创建,并使用节点操作添加到页面中时,方法效率高,但是没有innerHTML结合数组的形式效率高
实验: 测试地址
<!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>三种创建元素的区别</title>
</head>
<body>
<button>文档流执行完毕,测试document.write</button>
<button>测试innerHTML执行效率</button>
<button>测试innerHTML结合数组执行效率</button>
<button>测试creatElement执行效率</button>
<div class="test"></div>
<script>
// document.write 当所有文档流执行完毕时,执行这段代码会导致页面重绘
var btn = document.querySelectorAll('button');
btn[0].onclick = function () {
document.write('<div>当所有文档流执行完毕时,执行这段代码会导致页面重绘 document.write</div>');
}
// 测试innerHTML执行效率
var test = document.querySelector('.test');
btn[1].onclick = function () {
if (test.children[0]) {
test.removeChild(test.children[0]);
}
var div = document.createElement('div');
var d1 = +new Date();
for (var i = 0; i < 2000; i++) {
div.innerHTML += "<div style='width:100px;border:1px solid blue;'></div>"
}
var d2 = +new Date();
console.log(d2 - d1);
test.appendChild(div);
}
// 测试innerHTML加数组效率
btn[2].onclick = function () {
if (test.children[0]) {
test.removeChild(test.children[0]);
}
var div = document.createElement('div');
var d1 = +new Date();
var arr = [];
for (var i = 0; i < 2000; i++) {
arr.push("<div style='width:100px;border:1px solid blue;'></div>");
}
div.innerHTML = arr.join('');
test.appendChild(div);
var d2 = +new Date();
console.log(d2 - d1);
}
// creatElement效率测试
btn[3].onclick = function () {
if (test.children[0]) {
test.removeChild(test.children[0]);
}
var div = document.createElement('div');
var d1 = +new Date();
// 注意创建要添加的元素一定要写在循环内,因为如果写在外面,只创建一次,append添加之后就没有了。
for (var i = 0; i < 2000; i++) {
var divs = document.createElement('div');
divs.style.border = '1px solid blue';
divs.style.width = '100px';
div.appendChild(divs);
}
var d2 = +new Date();
test.appendChild(div)
console.log(d2 - d1);
}
</script>
</body>
</html>
DOM 重点核心(复习)#
DOM 就是文档对象模型(Document Object Model),是w3c组织推荐的处理可拓展标记语言(HTML或者XML)的标准编程接口。
W3C已经定义了一系列的 DOM 接口,通过这些接口 DOM 接口可以改变网页的内容、结构和样式。
- 对于 JavaScript,为了能够使 JavaScript 操作 HTML,JavaScript就有了一套自己的 DOM 编程接口。
- 对于 HTML,DOM 使得 HTML 形成了一棵 DOM 树。其中包含了文档(整个页面)、元素(页面中所有的标签)、节点(页面中所有的内容,文档是节点,元素是节点,属性也是节点)。
- 我们获取来的 DOM 元素是一个对象(object),所以称为文档对象模型。
关于 DOM 操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。
创建#
- document.write
- innerHTML
- createElement
增#
- appendChild
- insertBefore
删#
- removeChild
改#
主要是修改 DOM 元素的属性、内容、表单值等
- 修改元素属性:src、href、title等
- 修改普通元素内容:innerHTML、innerText
- 修改表单元素:value、type、disable等
- 修改元素样式:style、className
查#
主要获取查询 DOM 元素
- DOM 提供的 API 方法:getElementById、getElementByTagName 古老用法,不推荐
- H5 提供的新方法:querySelector、querySelectorAll 推荐
- 利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling)推荐
属性操作#
主要针对于自定义属性
- setAttribute:设置dom的属性值
- getAttribute:得到dom的属性值
- removeAttribute:移除属性
事件操作#
给元素注册事件、采取事件源.事件类型 = 事件处理程序
- onclick:鼠标点击左键触发
- onmouseover:鼠标经过触发
- onmouseout:鼠标离开触发
- onfocus:获得鼠标焦点触发
- onblur:失去鼠标焦点触发
- onmousemove:鼠标移动触发
- onmouseup:鼠标弹起触发
- onmousedown:鼠标按下触发
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了