JavaScript之DOM常用属性及方法详解
一.什么是DOM?
DOM:文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。 W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。
- 文档:一个页面就是一个文档,DOM 中使用 document 表示
- 元素:页面中的所有标签都是元素,DOM 中使用 element 表示
- 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示
注意:DOM 把以上内容都看做是对象。
如图:
对应的DOM树为:
要改变页面的某个东西,JS就需要获得对网页中所有元素进行访问的入口。这个入口,连同对HTML元素进行添加、移动、改变或移除的方法和属性,都是通过DOM来获得的。我们平时所说的操作DOM就是这么一回事。
浏览器会根据DOM模型,将结构化文档(HTML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。所有的节点和最终的树状结构,都有规范的对外接口。所以,DOM可以理解成网页的编程接口。DOM有自己的国际标准,目前的通用版本是DOM 3,DOM 4。
严格地说,DOM不属于JS,但是操作DOM是JS最常见的任务,而JS也是最常用于DOM操作的语言。DOM是浏览器厂商提供的js操作html的api,不同的浏览器厂商提供的api可能不同,所以dom存在兼容性问题(少部分)
那么,DOM都有哪些操作呢?
二.DOM操作
DOM分为四个重要部分(都是操作)
- 操作元素内容
- 操作元素属性
- 操作表单属性
- 操作元素类名
1.操作元素内容
想要操作元素内容,我们首先需要先获取这个元素,然后再对其进行操作
获取目标元素
在以前我们写css样式的时候,我们可以通过标签获取目标标签,也可以通过类,id,伪元素,等等,js获取相应对象也是类似的,在语法上稍有些不同,比如在以前我们是通过这些api来获取元素的:
- 根据 ID 获取: document.getElementById('id');方法可以获取带有 ID 的元素对象
- 根据标签名获取: document.getElementsByTagName('标签名'); 方法可以返回带有指定标签名的对象的集合
html5新增方式:
- 根据类名返回元素对象集合:document.getElementsByClassName(‘box’)
- 根据指定选择器返回(切记符号):
返回指定选择器第一个元素document.querySelector('.box')
返回指定选择器的所有元素对象集合document.querySelectorAll('.box')
代码示例:
<!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">盒子1</div>
<div class="box">盒子2</div>
<ul id="nav">
<li>首页</li>
<li>订单</li>
</ul>
<script>
document.getElementsByClassName('box');//根据类名返回元素对象集合
console.log('box');
var firstBox=document.querySelector('.box');//根据指定选择器返回第一个元素,切记里面的选择器需要加符号
console.log(firstBox);
var nav=document.querySelector('#nav');
console.log(nav);
var li=document.querySelector('li');
console.log(li);
var allbox=document.querySelectorAll('.box'); //返回指定选择器的所有元素对象集合
console.log(allbox);
</script>
</body>
</html>
获取html和body标签:
- 获取html:document.body
- 获取body标签:document.documentElement
2.获取目标元素内容
- inner.Text
- inner.HTML
这两个属性是可读写的, 可以获取元素里面的内容
两者区别:
他们的区别在于两点,第一种方法是老版本浏览器时有的属性,只能获取目标标签的内容,但是不能识别标签,第二种方法是W3C组织推出的,它不仅仅能获取目标标签的内容而且还能获取目标标签中的其他标签。
看以下例子对比:
box.innerText = '123'+'<br>'+'456';
// 相当于把目标标签的内容修改为123<br>456
box.innerHTML = '123'+'<br>'+'456';
// 此时就可以识别出里面的换行语句,输出结果为:132 换行 456
对比以上输出结果,容易得出innerHTML比innerText多了一种能识别html标签的功能。这既是好处也是弊端,弊端是因为攻击者也可以依靠此特性植入攻击代码,如xss攻击
3.操作元素属性
首先获取目标标签,然后再根据获取的标签对象找他有的属性,一般情况下,普通标签的属性无非是:href,src,title,alt
src =目标地址; (可以通过此语句改变目标文件,比如切换图片等)
href = 目标链接; (可以通过该语句改变目标网页);
alt = 目标替换文本; (在图片信息改变的时候,这个同时设置)
title = 目标图片提示信息;(在图片改变的时候,他的提示信息也是改变的)
代码示例:
<!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>
img {
width: 100px;
height: 200px;
}
</style>
</head>
<body>
<button id="hu">胡歌</button>
<button id="sa">Sakura</button><br>
<img src="JS/images/1.png" alt="">
<script>
//获取元素
var hu= document.getElementById('hu');
var sa= document.getElementById('sa');
var img = document.querySelector('img');
//注册事件
sa.onclick = function () {
img.src = 'JS/images/2.png'
img.title = 'sa';
}
hu.onclick = function () {
img.src = 'JS/images/1.png'
img.title = 'hu';
}
</script>
</body>
</html>
4.操作表单属性
利用 DOM 可以操作如下表单元素的属性:type、value、checked、selected、disabled
- type = 更换表单类型;
- value = 更换表单的内容 ; // 此时要注意修改表单的内容可不是修改他的innerHTML哦!
- disabled = true; // 可以设置表单是否不可用,默认为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>
</head>
<body>
<button>按钮</button>
<input type="text" value="输入内容" />
<script>
//获取元素
var btn = document.querySelector("button");
var input = document.querySelector("input");
//注册事件
btn.onclick = function () {
//表单里的值,通过value来修改 而不是innerHTML
input.value = "点我干嘛";
//如果想要某个表单被禁用,this指向的是事件函数的调用者 btn
this.disabled = true;
};
</script>
</body>
</html>
5.操作样式属性
通过 JS 修改元素的大小、颜色、位置等样式。
- element.style 行内样式操作
- element.className 类名样式操作
注意:
- JS 里面的样式采取驼峰命名法, 比如backgroundColor
- JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高
- 如果样式修改较多,可以采取操作类名方式更改元素样式。
- class因为是个保留字,因此使用className来操作元素类名属性
- className 会直接更改元素的类名,会覆盖原先的类名。
6.排他思想
顺序不能颠倒,处理所有人,留下我自己
代码示例:
<!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>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
</body>
<script>
//获取所有元素
var btns = document.getElementsByTagName("button");
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
//先把所有的按钮背景颜色去掉
for (var i = 0; i < btns.length; i++) {
btns[i].style.backgroundColor = "";
}
//再让当前的元素背景颜色为pink 留下我自己
this.style.backgroundColor = "pink";
};
}
</script>
</html>
三.自定义属性的操作
自定义属性目的∶
是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。自定义属性获取是通过getAttribute ('属性〉获取。
获取元素属性值: element.getAttribute('属性')//自己定义的
设置元素属性值: element.setAttribute('属性','值')//主要针对自定义属性
移除属性: removeAttribute('属性')
但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。H5给我们新增了自定义属性
设置H5自定义属性
H5规定自定义属性data-开头做为属性名并且赋值。比如<div data-index= “1” ></div>
或者使用JS设置,如:
element.setAttribute( 'data-inde,2)
获取H5自定义属性
- 兼容性获取element.getAttribute( 'data-index’);
- H5新增element.dataset.index或者element.dataset[ 'index’ ];
代码示例:
<!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>
<div getTime="20" data-index="3" data-list-name="Sakura"></div>
<script>
var div = document.querySelector("div");
console.log(div.getAttribute("getTime")); //20
div.setAttribute("data-time", 20);
// 获取自定义属性
console.log(div.getAttribute("data-index")); //3
// dataset 是一个集合里面存放了所有以data开头的自定义属性
console.log(div.dataset);
//DOMStringMap {index: '3', listName: 'Sakura', time: '20'}
console.log(div.dataset.index);//3
console.log(div.dataset["index"]);//3
console.log(div.dataset.listName);//Sakura
console.log(div.dataset["listName"]);//Sakura
</script>
</body>
</html>
四.节点操作
- 利用DOM提供的方法获取元素:逻辑性不强,繁琐
- 利用节点层级关系获取元素:逻辑性强,但是兼容性较差(更简单)
1.父级节点
node.parentNode //最近的一个父结点, 如果指定的节点没有父节点则返回 null
2.子节点
parentNode.childNodes 返回包含指定节点的子节点的集合,该集合为即时更新的集合
注意: 返回值里面包含了所有的子节点,包括元素节点,文本节点等。如果只想要获得里面的元素节点,则需要专门处理。 所以我们一般不提倡使用childNodes。
返回所有的子元素节点: parentNode.children 只读属性, 它只返回子元素节点,其余节点不返回
返回第一个子结点:parentNode.firstChild 返回最后一个子结点:parentNode.lastChild
注意:这两个方法返回的节点类型还包括元素节点,文本节点等,不一定是元素节点,使用时需要注意
返回第一个元素节点:parentNode.firstElementChild
返回最后一个元素节点:parentNode.lastElementChild
3.兄弟节点
返回当前元素的下一个兄弟元素节点:node.nextSibling;node.nextElementSibling
返回当前元素的上一个兄弟元素节点:node.previousSibling; node.previousElementSibling
4.创建,添加节点
添加一个新的元素分两步:
-
创建元素:document.createElement("元素名")
-
添加元素:1.在后面追加:node.appendChild(child);2.在前面加:node.insertBefore(child, 指定元素)
话不多说,上案例:
<!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>
<ul>
<li>hh</li>
</ul>
<script>
// 1. 创建节点元素节点
var li = document.createElement('li');
// 2. 添加节点 node.appendChild(child) node(父级) child(子级) 在后面追加元素
// 先获取父亲ul
var ul = document.querySelector('ul');
ul.appendChild(li);//创建的新的li
// 3. 添加节点 node.insertBefore(child, 指定元素);
var lili = document.createElement('li');
ul.insertBefore(lili, ul.children[0]);
</script>
</body>
</html>
5.删除,复制节点
删除:node.removeChild(child); //返回删除的节点
复制:node.cloneNode(true); //复制节点(克隆节点)
注意: 若括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子节点;若为false,则是浅拷贝,只复制节点本身,不克隆里面的子节点
6.三种动态创建元素区别
- document.write()
- element.innerHTML
- document.createElement()
- document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
- innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
- innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
- createElement() 创建多个元素效率稍低一点点,但是结构更清晰
7.元素节点的常用属性及方法
属性:
attributes:返回一个与该元素相关的所有属性的集合。
classList:返回该元素包含的 class 属性的集合。
className:获取或设置指定元素的 class 属性的值。
clientHeight:获取元素内部的高度,包含内边距,但不包括水平滚动条、边框和外边距。
clientWidth:返回该元素它内部的宽度,包括内边距,但不包括垂直滚动条、边框和外边距。
clientTop:返回该元素距离它上边界的高度。
clientLeft:返回该元素距离它左边界的宽度。
innerHTML:设置或获取 HTML 语法表示的元素的后代。
tagName:返回当前元素的标签名。 `
方法:
element.innerHTML = new html content :改变元素的 innerHTML element.attribute = value :修改属性的值 element.getAttribute() :返回元素节点的指定属性值。 element.setAttribute(attribute, value) :设置或改变 HTML 元素的属性值 element.style.property = new style :改变 HTML 元素的样式
五.常用DOM事件
1.鼠标事件
- 单击事件:onclick
- 双击事件:ondblclick
- 鼠标移入:onmouseover
- 鼠标移出:onmouseout
- 鼠标按下:onmousedown
- 鼠标抬起:onmouseup
2.键盘事件
- 按键按下:onkeydown
- 按键按下:onkeypress
- 按键松开:onkeyup
注意:
1.上述事件同时触发时,触发次序为:onkeydown-->onkeypress-->onkeyup
2.onkeypress事件保存按键值为ASCII码,onkeydown、onkeyup事件保存按键值是虚拟键码
3.onkeypress事件区分字母大小写,onkeydown、onkeyup事件不区分
4.onkeypress事件只能监听字母和数字,不能监听功能按键(如Ctrl),onkeydown、onkeyup事件都能监听
5.若一直按住按键不松开,会重复触发onkeydown和onkeypress事件
3.表单元素事件
- 获取焦点事件:onfocus
- 失去焦点事件:onblur
- 表单元素内容改变事件:onchange
- 元素获取用户输入事件:oninput
4.剪贴板事件
- 拷贝触发:oncopy
- 剪切触发:oncut
- 粘贴触发:onpaste
5.文档加载监听事件
- DOMContentLoaded:浏览器已完全加载 HTML,并构建了 DOM 树,但像 和样式表之类的外部资源可能尚未加载完成。
- loaded:浏览器不仅加载完成了 HTML,还加载完成了所有外部资源:图片,样式等。
转载自:https://juejin.cn/post/7154256329345875981