DOM编程
介绍
-
DOM编程
是指使用JavaScript与HTML文档中的DOM(文档对象模型)进行交互的过程。- 文档:整个HTML网页文档
- 对象:网页中的每一部分都转换为了对象
- 模型:使用模型表示对象之间的关系
-
DOM是HTML文档的树状结构表示,它允许开发者使用JavaScript来访问、操作和修改HTML元素、属性和样式。
-
通过DOM编程,开发者可以动态地创建、删除、修改和移动HTML元素,以及响应用户的交互事件。
-
节点
:Node--构成HTML文档最基本的单元- 常用节点:
- 文档:整个HTML文档
- 元素:HTML文档中的HTML标签
- 属性:元素的属性
- 文本:HTML中的文本内容(根据DOM标准,标签间的空白也算文本节点)
- 常用节点:
获取对象
- document.getElementById() 可以通过id获取对象
<button id="btn">这是一个按钮</button>
<script type="text/javascript">
//获取button对象
let btn = document.getElementById("btn");
console.log(btn);
//修改按钮的文字
btn.innerHTML = "修改后的文字";
</script>
事件
事件
是指在特定条件或用户操作发生时触发的动作或通知。- 事件可以是用户与程序交互的结果,例如点击按钮、输入文本、滚动页面等,也可以是程序内部的状态变化,例如定时器到期、数据加载完成等。
- 在HTML中,可以通过使用
事件属性
或事件监听器
来处理事件。
1. 事件属性:可以直接在HTML元素上使用事件属性来指定事件处理程序。- 常见的事件属性包括onclick(单击)、ondblclick(双击)、onmouseover、onkeydown等。
<button onclick="myFunction()">点击我</button>
<--点击后调用myFunction() -->
<button id="btn">点击我</button>
<script type="text/javascript">
//事件属性绑定回调函数
let btn = document.getElementById("btn");
btn.onclick = function(){
alert("你还真点了?");
}
</script>
2. 事件监听器:可以使用JavaScript代码来动态地添加事件监听器。通过这种方式,可以将事件处理程序与HTML元素分离,使代码更加清晰和可维护。常见的事件监听器方法包括addEventListener
和attachEvent
(用于旧版本的IE)。例如,要在按钮被点击时执行一个函数,可以使用addEventListener方法:
<button id="myButton">点击我</button>
<script type="text/javascript">
document.getElementById("myButton").addEventListener("click", myFunction);
</script>
文档加载
- 浏览器从上到下加载页面
- 将js代码写到下面就是为了先加载完页面在执行js代码
window.onload
事件在整个页面加载完成后触发
<script type="text/javascript">
window.onload = function () {
let btnElt = document.getElementById("btn");
btnElt.onclick = function () {
let value = document.getElementById("username").value;
alert(value);
}
}
</script>
<input type="text" id="username">
<input type="button" value="获取文本框的value" id="btn">
DOM查询
通过document
- 通过document对象调用获取元素节点
getElementById
通过id属性获取一个元素节点对象getElementsByTagName
通过标签名获取一组元素节点对象getElementsByName
通过name属性获取一组元素节点对象querySelector
或querySelectorAll
方法通过CSS选择器来获取元素节点。querySelector方法返回匹配选择器的第一个元素节点,而querySelectorAll方法返回匹配选择器的所有元素节点的对象集合。- 获取body标签:
document.getElementsByTagName("body")[0]
或document.body
- 获取html根标签:
document.documentElement
- 获取页面所有元素:
document.all
或document.getElementsByTagName("*")
- 通过class属性获取一组元素节点:
document.getElementsByClassName("box")
(IE8以下不兼容)或document.querySelector(".box")
- 如果要读取元素节点的属性,直接使用 元素.属性名 即可。class属性除外,需要使用 元素.calssName
<div id="myDiv">这是一个div元素</div>
<script type="text/javascript">
let element = document.getElementById("myDiv");
</script>
<p>这是一个段落</p>
<p>这是另一个段落</p>
<script type="text/javascript">
let elements = document.getElementsByTagName("p");
</script>
<input type="text" name="myInput" value="value">
<script type="text/javascript">
let elements = document.getElementsByName("myInput");
//如果要读取元素节点的属性,直接使用 元素.属性名 即可。class属性除外,需要使用 元素.calssName
alerrt(myInput[0].value);
</script>
<div class="box1" id="#myDiv">
<div class="div1">这是一个div元素</div>
<div class="div2">这是另一个div元素</div>
</div>
<script type="text/javascript">
//查找id为myDiv的元素下第一个div
let element = document.querySelector("#myDiv div");
//查找class为box1的元素下所有div
let elements = document.querySelectorAll(".box1 div");
</script>
- innrtHTML和innerText
innerHTML
属性用于获取或设置元素的HTML内容。它返回一个字符串,包含元素的所有HTML标记和文本内容。通过设置innerHTML属性,可以动态地修改元素的内容,包括添加、删除或修改HTML标记和文本。innerText
属性用于获取或设置元素的纯文本内容,即不包含任何HTML标记。它返回一个字符串,只包含元素的文本内容,而不包括HTML标记。通过设置innerText属性,可以动态地修改元素的文本内容。
<div id="myDiv">Hello <strong>World</strong></div>
<script type="text/javascript">
let element = document.getElementById("myDiv");
console.log(element.innerHTML);
// 输出:Hello <strong>World</strong>
element.innerHTML = "Goodbye";
</script>
<div id="myDiv2">Hello <strong>World</strong></div>
<script type="text/javascript">
let element = document.getElementById("myDiv2");
console.log(element.innerText);
// 输出:Hello World
element.innerText = "Goodbye";
</script>
通过具体元素
- 通过子节点
getElementsByTagName()
方法,返回当前节点的指定标签名后代节点(与document.getElementsByTagName()获取页面所有节点相比,具体元素.getElementsByTagName()只获取具体元素节点下的节点)childNodes
属性,表示当前节点的所有子节点,包括文本节点children
属性,表示当前节点的所有子节点,不包括文本节点firstChild
属性,表示当前节点的第一个子节点,包括空白文本节点firstElementChild
属性,表示当前节点的第一个子元素,不包括空白文本节点。注意该属性IE8以下不兼容。lastChild
属性,表示当前节点的最后一个子节点,包括空白文本节点
<div id="myDiv">
<p id="p1">你居住的城市?</p>
<ul id="city">
<li id="bj">北京</li>
<li>上海</li>
<li>广州</li>
</ul> <p>你使用的手机品牌?</p>
<ul id="phone">
<li id="mi">小米</li>
<li id="apple">苹果</li>
<li >三星</li>
</ul> <button type="button" id="btn1">getElementsByTagName</button>
<button type="button" id="btn2">childNodes</button>
<button type="button" id="btn3">children</button>
<button type="button" id="btn4">firstChild</button>
<button type="button" id="btn5">lastChild</button>
</div>
window.onload = function () {
// 通过具体元素节点调用
//1.getElementsByTagName()方法,返回当前节点的指定标签名后代节点
document.getElementById("btn1").addEventListener("click", function() {
let descendants = document.getElementById("city").getElementsByTagName("*");
alert("city的后代节点,包括空文本节点:" + descendants.length);
});
//2.childNodes 属性,表示当前节点的所有子节点,包括文本节点
document .getElementById("btn2").addEventListener("click", function() {
let childNodes = document.getElementById("city").childNodes;
let count = 0;
for (let i = 0; i < childNodes.length; i++) {
if (childNodes[i].nodeType !== 3) {//nodeType==3是文本类型
count++;
}
}
alert("city的所有子节点的数量,不包括文本节点:" + count);
});
//3.children属性,表示当前节点的所有子节点,不包括文本节点
document.getElementById("btn3").addEventListener("click", function() {
let children = document.getElementById("phone").children;
alert("phone的所有子节点的数量,不包括文本节点:" + children.length);
});
//4.firstChild属性,表示当前节点的第一个子节点
document.getElementById("btn4").addEventListener("click", function() {
let firstChild = document.getElementById("phone").firstChild;
alert("phone的第一个子节点:" + firstChild.nodeName);
});
//5.lastChild属性,表示当前节点的最后一个子节点
document.getElementById("btn5").addEventListener("click", function() {
let lastChild = document.getElementById("phone").lastChild;
alert("phone的最后一个子节点:" + lastChild.nodeName);
});
}
ul {
display: flex;
list-style-type: none;
}
li {
margin-right: 10px;
}
- 通过父节点和兄弟节点
parentNode
属性,返回指定节点的父节点,无论父节点是什么类型(可以是元素节点、文本节点、注释节点等)。parentElement
属性,返回指定元素节点的父元素节点。如果父节点不是元素节点,则返回null。previousSibling
属性,获取当前节点的前一个兄弟节点,无论兄弟节点是什么类型(可以是元素节点、文本节点、注释节点等)。previousElementSibling
属性,获取当前节点的前一个兄弟元素。IE8以下不支持nextSibling
属性,获取当前节点的后一个兄弟节点,无论兄弟节点是什么类型(可以是元素节点、文本节点、注释节点等)。nextElementSibling
属性,获取当前节点的后一个兄弟元素。IE8以下不支持。
<div id="myDiv">
<p id="p1">你居住的城市?</p>
<ul id="city">
<li id="bj">北京</li>
<li>上海</li>
<li>广州</li>
</ul> <p>你使用的手机品牌?</p>
<ul id="phone">
<li id="Mi">小米</li>
<li id="Apple">苹果</li>
<li id="Samsung">三星</li>
</ul> <button type="button" id="btn1">parentNode</button>
<button type="button" id="btn2">previousSibling</button>
<button type="button" id="btn3">nextSibling</button>
</div>
//定义一个函数,专门来指定元素单击响应函数
function myClick(elmId,fun) {
let btn = document.getElementById(elmId);
btn.onclick = fun;
}
window.onload = function () {
//为id为bj的节点的父节点city,绑定单击响应函数
myClick("btn1",function () {
let bj = document.getElementById("bj");
// let bjPn = bj.parentNode;
let bjPn = bj.parentElement;
alert(bjPn.innerText);
})
//为id为Apple的前一个兄弟节点绑定单击相应函数
myClick("btn2",function () {
let apple = document.getElementById("Apple");
// let ps = apple.previousSibling;
let ps = apple.previousElementSibling;
alert(ps.innerText);
})
myClick("btn3",function () {
let apple = document.getElementById("Apple");
// let ns = apple.nextSibling;
let ns = apple.nextElementSibling;
alert(ns.innerText);
})
}
DOM增删改
-
增加元素:
createElement
方法,创建新的HTML元素。需要一个标签名作为参数,会根据标签名创建节点对象createTextNode
方法,创建新的文本节点。需要一个文本作为参数。appendChild
方法,向父节点添加新的子节点。语法:父节点.appendChild(新子节点)
insertBefore
方法,向指定子节点前面插入新的子节点。语法:父节点.insertBefore(新子节点,指定子节点)
repaceChild
方法,替换子节点。语法:父节点.repaceChild(新子节点,旧子节点)
-
删除元素:
removeChild
方法,删除子节点。语法:父节点.repaceChild(子节点)
。- 可以使用
指定子节点.parentNode.removeChild(指定子节点)
来删除不知道父节点的子节点。该方法更常用。
-
修改元素:
setAttribute
方法,改变元素的属性。innerHTML
方法,也可以改变元素属性。此外,该方法也可以实现DOM的增删改,但是建议与前面的方法结合使用。
<div class="box1">
<ul id="city">
<p>你喜欢那个城市?</p>
<li id="bj">北京</li>
<li>上海</li>
<li id="dj">东京</li>
<li id="hsd">华盛顿</li>
</ul></div>
<div class="box2">
<ul id="btn">
<li><button type="button" id="btn1">创建一个“广州”节点,添加到#city下</button> </li>
<li><button type="button" id="btn2">将“广州”节点插入到#bj前</button> </li>
<li><button type="button" id="btn3">使用“广州”节点替换#dj</button> </li>
<li><button type="button" id="btn4">删除#hsd节点</button> </li>
<li><button type="button" id="btn5">读取#city内的HTML代码</button> </li>
</ul></div>
//创建单击响应函数
function myClick(btnId,fun) {
let btn = document.getElementById(btnId);
btn.onclick = fun;
}
window.onload = function () {
//创建一个“广州”节点,添加到#city下
//1. 为按钮绑定单击响应函数
myClick("btn1",function () {
//2.创建广州节点
let gz = document.createElement('li');
//3. 创建广州文本节点
let gzText = document.createTextNode("广州");
//4. 为广州节点绑定文本子节点
gz.appendChild(gzText);
//也可以直接修改gz节点的innerHTML或innerText
// gz.innerHTML = "广州";
//5. 为#city绑定广州子节点
let city = document.getElementById("city");
city.appendChild(gz);
})
// 将“广州”节点插入到#bj前
//1. 为按钮绑定单击响应函数
myClick("btn2",function () {
//2.创建广州节点
let gz = document.createElement("li");
//3.设置gz的文本内容
gz.innerText = "广州";
//4. 获取#bj节点
let bj = document.getElementById("bj");
//5. 将gz插入在#bj前
bj.parentNode.insertBefore(gz,bj);
})
// 使用“广州”节点替换#dj
myClick("btn3",function () {
//2.创建广州节点
let gz = document.createElement("li");
//3.设置gz的文本内容
gz.innerText = "广州";
//4. 获取#bj节点
let dj = document.getElementById("dj");
//5. 将gz替换#dj
dj.parentNode.replaceChild(gz,dj);
})
// 删除#hsd节点
myClick("btn4",function () {
//获取#hsd节点
let hsd = document.getElementById("hsd");
//删除
hsd.parentNode.removeChild(hsd);
})
// 读取#city内的HTML代码
myClick("btn5",function () {
let city = document.getElementById("city");
alert(city.innerHTML);
})
}
DOM操作CSS
读取和修改内联样式
元素.style.样式名=样式值
通过js修改元素内联样式,因为内联样式显示优先级较高,就覆盖了样式表中的样式。但是如果原样式有!important
关键字则js修改样式无效,因此尽量不要为样式使用该关键字。- 如果css样式名中含有
-
,需要将该样式修改为驼峰命名法。例如background-color
修改为backgroundColor
box1.style.width = "300px";//将box1的width修改为300px
box1.style.backgroundColor = "blue";//修改box1的颜色
alert(box1.style.width);//读取内联样式
元素.style.样式名
也可以读取元素的内联样式
读取和修改样式
getComputedStyle
方法可以读取元素的当前样式- 语法
getComputedStyle(要获取的元素,伪元素/null)
。 - 该方法返回一个对象,封装了当前元素对应样式。
- 可以通过
对象.样式名
获取样式,如果获取的样式没有设置,会返回一个真实值,如width不会返回auto,而是实际的值。IE8以下不支持。
- 语法
元素.currentStyle.样式名
可以读取元素的当前样式,只有IE支持。- 以上方法/属性获取的样式都是只读的,要修改必须通过style属性
function getStyle(obj,name) {
//普通浏览器
if (window.getComputedStyle){ //属性为找到返回undified
return getComputedStyle(obj,null)[name];
}else {
//IE8
return obj.currentStyle[name];
}
}
练习
1 图片切换
- 要求
- 当点击按键时切换图片
- 实现4张图片的循环切换
- info显示共几张和当前是第几张图片
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>练习1-图片切换</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
#outer{
width: 476px;
margin: 50px auto;
padding: 10px;
background-color: #bbffaa;
text-align: center;
}
</style>
<script type="text/javascript">
//要切换图片就是要修改img标签的src
// 可以使用数组保存图片的路径
// 使用变量保存当前索引
//点击按钮后,重新设置信息
</script>
</head>
<body>
<div id="outer">
<p id="info">一共 4 张图片,当前第 张</p>
<img src="img/bomb_0.png" alt="bomb1"/>
<button type="button" id="prev">上一张</button>
<button type="button" id="next">下一张</button>
</div>
</body>
</html>
2 全选练习
- 要求
- 当点击全选,所有多选框都选择;当点击全不选,所有多选都不选
- 当点击反选,选择之前选择的剩余未选择的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>练习2 全选练习</title>
<style type="text/css">
input[type="checkbox"] {
display: inline-block;
margin-right: 10px;
}
</style>
<script type="text/javascript" src="../js/练习2-全选练习.js"></script>
</head>
<body>
<form id="sport">
<p>你爱好的运动是?</p>
<input type="checkbox" name="sport" value="足球" id="football">足球
<input type="checkbox" name="sport" value="篮球" id="basketball">篮球
<input type="checkbox" name="sport" value="乒乓球" id="pingpong">乒乓球
<input type="checkbox" name="sport" value="羽毛球" >羽毛球<br>
</form>
<button type="button" id="btn1">全选</button>
<button type="button" id="btn2">全不选</button>
<button type="button" id="btn3">反选</button>
<button type="button" id="btn4">提交</button>
</body>
</html>
- 答案
//创建绑定函数
function myClick(elemId,fun) {
let btn = document.getElementById(elemId);
btn.onclick = fun;
}
window.onload = function () {
let elem1 = document.getElementById("football");
let elem3 = document.getElementById("pingpong");
let elem2 = elem3.previousElementSibling;
let elem4 = elem3.nextElementSibling;
// alert(elem2.innerHTML);
// alert(elem4.innerHTML);
let elemArr = [elem1,elem2,elem3,elem4];
// 全选
myClick("btn1",function () {
for (let i = 0; i < elemArr.length; i++) {
elemArr[i].checked = true;
}
})
// 全不选
myClick("btn2",function () {
for (let i = 0; i < elemArr.length; i++) {
elemArr[i].checked = false;
}
})
// 反选
myClick("btn3",function () {
for (let i = 0; i < elemArr.length; i++) {
if (elemArr[i].checked){
elemArr[i].checked = false;
}else {
elemArr[i].checked = true;
}
}
})
}
3 表单的增删改
- 要求:
- 当点击Delete,提示是否真的删除。点击确定,删除,点击取消,不删除。
- 在name、email、salary中填写内容,点击submit后,添加记录