一、DOM的概念
文档对象模型(DOM,Document Object Module)是W3C组织推荐的处理可扩展标志语言的标准编程接口,它允许程序和脚本动态的访问和更新文档的内容、结构和样式。
HTML的DOM操作是将文档里所有的内容(包括标签、标签里的内容、标签属性甚至注释等)都当做一个HTML的节点。所有的节点按照组织结构构成一个树形结构,最上层节点就是我们的整个文档(document).
从上图中可以看出,所有的节点都是从文档开始的,JS里有一个内置对象document,指的就是这个属性结构的根节点。所以,使用JavaScript可以获取和修改这个树形结构的所有节点,这个过程我们就可以称之为DOM操作。
<script>
window.onload = function () {
var pic = document.getElementById('pic');
console.log(pic.height);
var one = document.getElementsByClassName('one')[0];
var btn = document.getElementById('btn');
btn.onclick = function(){
one.textContent = '<a href="http://www.baidu.com">hello</a>'
one.style.color = 'red';
}
}
</script>
</head>
<body>
<p class="one">我是一个p</p>
<img id="pic" src="IMG_0120.JPG" alt="" width="200px">
<button id="btn">点我呀</button>
</body>
上面的一段代码的作用是界面上的一个图片元素,并打印这个图片元素的高度,获取一个按钮和一个p标签,点击按钮时,修改p标签的显示的文字。这段代码需要注意以下问题: 所有的DOM操作代码,都建议写在window.onload事件函数里,当整个浏览器窗口加载完成以后,再执行DOM操作,否则可能会出现找不到元素的情况。
除此之外,上述代码还有几个问题:
- document.getElementsByClassName这个函数,在老版本的IE浏览器里不支持。
- one.textcontent属性在老版本的IE浏览器里同样也不支持。
如果要解决上述的问题,需要额外再写很多处理兼容性问题的代码,加大开发难度。
由于原生DOM的局限性,所以在前端开发中,基本上不会使用原生DOM来操作页面上的元素,早期操作页面元素都是使用jQuery这种类型的JS库来实现。随着Angular,React以及Vue的发展,jQuery也正在退出历史舞台。但是无论是jQuery还是Vue,它们在操作页面元素时,底层都是通过原生DOM来实现的。
二、DOM操作
常见的DOM操作主要分为一下几个步骤:
- 获取页面的标签元素
- 操作页面上的标签
- 获取和修改标签属性
- 增加和删除标签
- 事件处理
1. 查找标签
要操作页面上的元素,首先需要查找到页面上的元素。在JS里有一个内置的顶级对象window,它用来表示当前的显示器窗口,所有的元素都从window对象里开始查找。
window.console.long("hello"); // console其实也是window对象里的一个对象
通常情况下,window.
可以省略,例如,将window.console
直接写成console
,将window.document
简写成为document
.
在window中还有一个对象属性document
,用来表示当前页面上的文档对象。它是整个DOM操作的顶级对象,通过document
对象,我们可以操作页面上的所有内容。
document.getElementById(id); // 根据id从页面上查找到对应的元素
document.getElementsByClassName(className); // 根据 类名 从页面上查找到所有的标签
document.getElementsByTagName(tagName); // 根据标签名查找到页面上的所有标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="one"></div>
<div id="two"></div>
<span></span>
<script>
window.onload = function () {
window.document.getElementById("two");
document.getElementsByClassName("one");
document.getElementsByTagName("span");
let oneDiv = document.getElementsByClassName("one")[0];
let spanElement = oneDiv.getElementsByTagName("span")[0];
/*
// getElementById(id) 方法只能由 document 来调用,不能使用其他DOM对象调用!
oneDiv.getElementById("link"); // 运行报错!!!
*/
}
</script>
</body>
</html>
注意事项:
- getElementById(id)方法只能通过document这个DOM对象调用,不能通过其他DOM对象调用。
- getElementsByClassName(className)方法在老版本的IE浏览器里不支持,会有浏览器兼容性问题。
2. 操作页面元素
获取到标签元素以后,可以通过相关的方法获取和修改标签的属性,删除和新增标签以及添加事件处理。
3. 标签的属性
不同的标签元素支持不同的属性,能够调用的方法不同,具体可以通过文档查看每个标签类型具体支持的方法。下面我们只列举出一些常见标签的常见属性和方法。
方法和属性名 | 作用 | 适用范围 |
---|---|---|
innerHTML | 获取和设置标签上的内容。如果内容里有标签,标签会被解析 | 所有HTML标签 |
innerText | 获取和设置标签上的内容。如果内容里有标签,标签不会被解析,以存文本的形式显示 | 所有HTML标签 |
textContent | 和innerText的功能一样,为了解决浏览器兼容性问题 | 所有的HTML标签 |
style | 获取和设置标签的行内样式 | 所有的HTML标签 |
src | 获取和设置img标签的图片源 | img标签 |
href | 获取和设置a标签的链接地址 | a标签 |
value | 表示input输入框里的内容 | input标签元素 |
type | 标签input输入框的类型 | input标签元素 |
其他类型标签的属性,都可以通过标签名.属性名的形式来获取和修改。具体哪个标签能够使用哪个属性,可以参考标签属性章节。
4. 添加和删除标签
- remove()方法: 将当前标签从父标签里移除掉。
- removeChild(child)方法: 从父标签里移除指定的子标签。
- document.createElement(tagName)方法: 创建一个标签。
- appendChild(child)方法: 将子标签添加到父标签里。
5. 事件处理
JS是一个事件驱动型的语言,几乎所有的逻辑都由事件来完成。事件可能是用户在某些内容上的点击、鼠标经过某个特定元素或按下键盘上的某些按键,事件还可能是Web浏览器中发生的事情,比如说某个Web页面加载完成,或者是用户滚动窗口或改变窗口大小。说白了,事件是文档或浏览器中发生的特定交互瞬间!
JS的事件处理方式分为事件冒泡(点击一个元素时,会先触发这个元素的点击事件,然后再逐级调用各个父元素的点击事件)和事件捕获(和时间冒泡调用顺序相反)两种方式,默认的事件处理方式是事件冒泡。
添加事件的方式
-
直接给DOM对象添加onclick属性,指定一个函数。
document.getElementById("father").onclick = function () {
console.log("father被点击了");
};
document.getElementById("son").onclick = function () {
console.log("son被点击了");
};
- 调用DOM对象的addEventListener(eventName,eventFunction)方法给DOM添加事件。
document.getElementById('father').addEventListener("click", function () {
console.log("father被点击了");
});
document.getElementById('son').addEventListener("click", function () {
console.log("son被点击了");
});
6. 事件对象
每次事件产生时,在事件处理函数里都会有创建事件对象。这个事件对象会存储事件发生时的相关信息,例如点击事件时光标的位置,键盘事件是按下的按键等。通过这个事件对象,可以对事件进行相关的处理。
document.getElementById("commit").onclick = function(e) {
// 获取点击事件时光标的位置信息
console.log(e.screenX);
// 阻止事件的默认行为
e.preventDefault();
};
document.getElementById("input").onkeydown = function (e) {
if (e.key == 'Enter') { // 获取键盘事件按下的按键
console.log("hello");
}
};