17 JavaScript DOM
1 概述
所谓DOM,全称 Docuemnt Object Model 文档对象模型。
什么对象?文档对象?
在文档中一切皆对象,比如html,body,div,p等等都看做对象,那么我们如何来点击某个盒子让它变色呢?DOM 为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。目的其实就是为了能让js操作html元素而制定的一个规范。
解析
HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树,getElementById是获取内中DOM上的元素节点。然后操作的时候修改的是该元素的属性。
DOM树(一切皆是节点)
上图可知,在HTML当中,一切都是节点:(非常重要)
- 元素节点:HMTL标签。
- 文本节点:标签中的文字(比如标签之间的空格、换行)
- 属性节点::标签的属性
整个html文档就是一个文档节点。所有的节点都是Object。
2 DOM可以作什么
- 找对象(元素节点)
- 设置元素的属性值
- 设置元素的样式
- 动态创建和删除元素
- 事件的触发响应:事件源、事件、事件的驱动程序
3 清除DOM的结构
- 获取文档对象:document
- 获取html:document.documentElement
- 获取body: document.body
4 获取元素的三种方式
//方式一:通过id获取单个标签
var oDiv1 = document.getElementById("box1");
//方式二:通过 标签名 获得 标签数组,所以有s
var oDiv2 = document.getElementsByTagName("div")[0];
//方式三:通过 类名 获得 标签数组,所以有s
var oDiv3 = document.getElementsByClassName("box")[0];
5 节点操作
5-1 setAttribute()&getAttribute()
获取节点下的属性,设置节点下的属性
<h2>你要买什么课程</h2>
<p title="请选择购买的课程">本课程是web全栈课程,期待你的购买</p>
<ul id="classList">
<li class="item">JavaScript</li>
<li class="item">CSS</li>
<li>DOM</li>
</ul>
<script>
var oP = document.getElementsByTagName('p')[0];
//获取属性值 有一个必须的参数,这个节点的名字
var title = oP.getAttribute('title'); //获取属性名和值
console.log(title);
//设置属性名和值 setAttribute(name,value)
oP.setAttribute('id','box');
</script>
5-2 节点对象三个属性
在文档对象模型(DOM)中,每个节 点都是一个对象。DOM节点有三个重要的属性 :
1. nodeName:节点的名称
2. nodeValue :节点的值
3. nodeType:节点的类型
1. nodeName属性:节点的名称,是只读
1.元素节点的nodeName与标签名相同
2.属性节点的nodeName.与属性的名称相同
3.文本节点的nodeName永远是#text
4.注释节点的nodeName永远是#comment
2. nodeValue属性:节点的值
1.元素节点的nodeValue是undefined 或null
2.文本节点的nodeValue是文本自身
3.属性节点的nodeValue是属性的值
4.注释节点的nodeValue是注释自身
3. nodeType属性:节点的类型,是只读的。
以下常用的几种结点类型:
元素节点:节点类型
元素:1
属性:2
文本:3
注释:8
文档:9
<div id="box" title="我是文本">
我是一个文本节点<!--我是一个注释节点-->
</div>
<script>
//元素节点
var oDiv = document.getElementById('box');
console.log(oDiv.nodeName + ' | ' + oDiv.nodeValue
+ ' | ' + oDiv.nodeType); //DIV | null | 1
//属性节点
var attrNode = oDiv.attributes[0]; //获取oDiv下的属性。{0: id, 1: title, id: id, title: title, length: 2}
console.log(attrNode.nodeName + ' | ' + attrNode.nodeValue
+ ' | ' + attrNode.nodeType); // id | box | 2
//文本节点
var textNode = oDiv.childNodes[0]; //[text, comment, text]
console.log(textNode.nodeName + ' | ' + textNode.nodeValue
+ ' | ' + textNode.nodeType);
//注释节点
var commentNode = oDiv.childNodes[1]; //[text, comment, text]
console.log(commentNode.nodeName + ' | ' + commentNode.nodeValue
+ ' | ' + commentNode.nodeType);
//文档节点
console.log(document.nodeType);
</script>
5-3 导航查找标签
版本一(推荐):
<div class="c2">
<div class="c3">
<ul class="c4">
<li>000</li>
<li class="c5" id="box">111</li>
<li>222</li>
<li>333</li>
</ul>
</div>
</div>
<script>
var c5 = document.getElementsByClassName('c5')[0];
//获取父集节点
console.log(c5.parentElement);
//获取父亲节点下第一个儿子标签
console.log(c5.parentElement.firstElementChild);
//获取父亲节点下的最后一个儿子标签
console.log(c5.parentElement.lastElementChild);
//获取父亲节点下的所有儿子标签(不包含text)
console.log(c5.parentElement.children);
//获取c5节点下的下一个标签
console.log(c5.nextElementSibling);
//获取c5节点下的下下一个标签
console.log(c5.nextElementSibling.nextElementSibling);
//获取c5节点下的上一个标签
console.log(c5.previousElementSibling);
//获取c5节点下的上上一个标签
console.log(c5.previousElementSibling.previousElementSibling);
</script>
版本二:
<div class="previous">我是上一个兄弟</div><div id="father"><p>lxx</p><p>lww</p></div><div class="sibling">我是下一个兄弟</div>
<script>
var oFather = document.getElementById('father');
console.log(oFather.childNodes); //获取father下的所有元素(包含text)
console.log(oFather.firstChild); //获取集合的第一个元素
console.log(oFather.childNodes[0]); //获取集合的第一个元素
console.log(oFather.lastChild); //获取集合的第二个元素
console.log(oFather.childNodes[oFather.childNodes.length - 1]); //获取集合的第二个元素
console.log(oFather.parentNode); //获取父集节点
console.log(oFather.parentNode.lastElementChild); //获取父亲节点下的最后一个儿子标签
console.log(oFather.nextSibling); //获取'father'下一个兄弟节点
console.log(oFather.previousSibling); //获取'father‘上一个兄弟节点
</script>
如果有换行文档需要用函数过滤掉
<div class="previous">我是上一个兄弟</div>
<div id="father">
<p>lxx</p>
<p>lww</p>
</div>
<div class="sibling">我是下一个兄弟</div>
<script>
var oFather = document.getElementById('father');
//获取id‘father’的元素节点
function get_childNodes(fatherNode) {
var nodes = fatherNode.childNodes;
var arr = [];
for (var i=0; i<nodes.length; i++){
if (nodes[i].nodeType === 1){
arr.push(nodes[i]);
}
}
return arr;
}
console.log(get_childNodes(oFather));
//获取id‘father’的下一个元素节点
function get_nextSibling(n) {
var x = n.nextSibling;
while (x && x.nodeType != 1){
x = x.nextSibling;
}
return x;
}
console.log(get_nextSibling(oFather));
//获取id‘father’的上一个元素节点
function get_previousSibling(n) {
var x = n.previousSibling;
while (x && x.nodeType != 1){
x = x.previousSibling;
}
return x;
}
console.log(get_previousSibling(oFather));
</script>
5-4 节点增删改查
版本一:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button class="add_btn">添加节点</button>
<button class="del_btn">删除节点</button>
<button class="replace_btn">替换节点</button>
<div class="c1">
<h3>hello JS!</h3>
<h3 class="c2">hello world</h3>
</div>
<script>
var add_btn = document.querySelector('.add_btn');
var del_btn = document.querySelector('.del_btn');
var replace_btn = document.querySelector('.replace_btn');
var c1 = document.querySelector('.c1');
var c2 = document.querySelector('.c2');
add_btn.onclick = function () {
//创建节点
var ele = document.createElement('img'); //<img>
ele.src = "https://img1.baidu.com/it/u=1269478472,4160885730&fm=26&fmt=auto&gp=0.jpg"
console.log(ele);
//插入节点
// c1.appendChild(ele); //追加一个子节点(作为最后的节点)
c1.insertBefore(ele,c2); //把增加的节点放到某个节点的前面
}
//删除节点
del_btn.onclick = function () {
c1.removeChild(c2); //获得要删除的元素,通过父元素调用删除
}
//替换节点(语法:.replaceChild(newnode,某个节点))
replace_btn.onclick = function () {
//创建替换节点
var ele = document.createElement('img'); //<img>
ele.src = "https://img1.baidu.com/it/u=1269478472,4160885730&fm=26&fmt=auto&gp=0.jpg"
console.log(ele);
c1.replaceChild(ele,c2);
}
</script>
</body>
</html>
版本二:
<div id="box">
<p id="active" k1='v1'>lxx</p>
</div>
<!--
动态的操作节点
1.创建节点 createElement()
2.插入节点 appendChild()
insertBefore(newNode,node)
3.删除节点 removeChild()
4.替换节点 replaceChild(newNode,node)
5.创建文本节点 createTextNode()
-->
<script>
//获取节点
var oDiv = document.getElementById('box');
//创建标签名
var newNode1 = document.createElement('p');
//获取k1属性的值
console.log(ele.getAttribute('k1'));
//设置 class类名 和 value值
newNode1.setAttribute('class','active');
/*
方式一:
创建文本节点对象
var textNode = document.createTextNode('alex');
选择插入的位置
newNode.appendChild(textNode);
*/
//方法二:插入文本或者跟标签一起插入(渲染文本和标签)
newNode1.innerHTML = '<a href="#">alex@qq.com</a>';
/*
方法二:插入纯字符串文本(只能渲染文本)
newNode.innerText = '<a href="#">alex@qq.com</a>';
*/
//插入标签(默认插入最后)
oDiv.appendChild(newNode1);
//插入 insertBefore 的方法
//获取节点
var oActive = document.getElementById('active');
//创建标签名
var newNode2 = document.createElement('p');
//插入内容
newNode2.innerHTML = '<a href="#">lxx@qq.com</a>';
//第一个参数是新插入的节点,第二个参数是参考的节点
oDiv.insertBefore(newNode2,oActive);
//替换 replaceChild 方法
//创建标签名
var newNode3 = document.createElement('a');
//设置 class类名 和 value值
newNode3.setAttribute('href','http://www.baidu.com');
//插入内容
newNode3.innerHTML = '百度一下';
//第一个参数是要替换的参数,第二参数是替换的新值
oDiv.replaceChild(newNode3,oActive);
//删除节点
// oDiv.removeChild(oActive);
// newNode1 = null; //释放对象
</script>
5-5 节点的样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#classList{
color: white;
background-color: black;
width: 200px;
height: 200px;
text-align: center;
}
</style>
</head>
<body>
<p id="box">LXX</p>
<script>
var oP = document.getElementById('box');
/*
方式一(直接设置为行内):
console.log(oP.style);
oP.style.color = 'white';
oP.style.backgroundColor = 'black';
oP.style.width = '250px';
oP.style.height = '250px';
oP.style.textAlign = 'center';
oP.style.lineHeight = '250px';
*/
//方式二(通过类的方式):
oP.setAttribute('class', 'highLight')
</script>
</body>
</html>
5-6 CSS选择器标签
<div class="c2">
<div class="c3">
<ul class="c4">
<li class="c5">000</li>
<li class="c5" id="box">111</li>
<li>222</li>
<li>333</li>
</ul>
</div>
</div>
<script>
//css方法获取元素节点
var dom = document.querySelector(".c2 .c3 .c4 .c5");
console.log(dom);
//css方法获取多个相同的元素节点
var els = document.querySelectorAll('ul li');
console.log(els);
</script>
5-7 文本操作
<div class="name"><span>lxx</span></div>
<script>
//查询文本
var oDiv = document.querySelector('.name');
console.log(oDiv.innerHTML); //标签和文本都渲染
console.log(oDiv.innerText); //只渲染文本
//设置文本
oDiv.onclick = function () {
// oDiv.innerHTML = '大帅'; //修改值
oDiv.innerHTML = '<a href="#">大帅</a>'; //渲染标签和文本
// oDiv.innerText = '<a href="#">大帅</a>'; //只渲染文本
}
</script>
5-8 value查找方法
像input标签,select标签 以及textarea标签是没有文本的,但是显示内容由value属性决定
- value操作
<input type="text" class="c1" value="hello world"><button class="btn">change</button>
<script>
var btn = document.getElementsByClassName('btn')[0];
btn.onclick = function () {
//类查找
// var ele = document.querySelector('.c1');
// ele.value = 'hello JS!';
//导航查找
this.previousElementSibling.value = 'hello JS!';
}
</script>
5-9 select取值赋值
<select name="" id="box">
<option value="henan">河南</option>
<option value="hebei">河北</option>
<option value="hunan">湖南</option>
</select>
<button class="btn">change</button>
<script>
//select标签
var sel = document.querySelector('#box');
console.log(sel.value); //取值
var btn = document.getElementsByClassName('btn')[0];
btn.onclick = function () {
sel.value = 'hebei'; //赋值
}
</script>
5-10 textarea取值赋值
<textarea id="text">lxx</textarea>
<script>
//textarea标签
var ele = document.querySelector('#text');
console.log(ele.value); //取值
ele.value = 'welcome to JS'; //赋值
</script>
5-11 class属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.c1{
background-color: #83c44e;
}
.c2{
color: red;
}
.hide{
display: none;
}
</style>
</head>
<body>
<div class="c1">hello world</div>
<script>
var ele = document.querySelector('.c1');
ele.onclick = function () {
this.classList.add('c2'); //添加类样式
this.classList.remove('c1'); //删除类样式
console.log(this.className); //打印节点下样式的类名
}
ele.ondblclick = function () {
this.classList.add('hide'); //隐藏
}
</script>
</body>
</html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本