一、DOM介绍
DOM 是document object model ,文档对象模型:
-
D(document):document的意思是文档,在dom中会将HTML这个页面给解析为一个文档,并在解析的同时会提供一个 document对象。
document对象:每个载入浏览器的HTML文档都会成为document对象,使我们可以从脚本中对HTML页面中的所有元素进行访问,因为document对象是window对象的一部分,所以也可通过window.doucument进行访问。
-
O(object):object就是对象,相必大家对于这个都不陌生,而DOM则把HTML页面中的所有元素都解析为一个对象。
-
M(model):M代表的就是model(模块),主要表现的是dom里面各个对象之间的关系。
它是W3C 制定的浏览器提供的对HTML文档操作的接口,把文档中的代码内容翻译成一个对象模型,在这个模型中,所有相关的标签属性注释文本等等12种数据,都翻译为一种类型的对象,统称节点对象,节点对象之间,在文档模型数据结构中存在某种关系:根节点 父子节点 同胞节点等等。
根据 DOM规定,HTML 文档中的每个成分都是一个节点。(一棵节点树中的所有节点彼此都是有关系的。 )
- 整个文档是一个文档节点(nodeType为9)
- 每个 HTML 标签/body标签是一个元素节点(nodeType为1)
- 包含在 HTML 元素中的文本是文本节点(如换行、包裹在html标签中的文本 nodeType为3)
- 每一个 HTML 属性是一个属性节点(nodeType为2)
- 注释属于注释节点(nodeType为8)
例如下代码:
<html>
<head>
<title>DOM Tutorial</title>
</head>
<body>
<h1>DOM Lesson one</h1>
<p>Hello world!</p>
</body>
</html>
<!--
1. <head> 和 <body> 的父节点是 <html> 节点,文本节点 "Hello world!" 的父节点是 <p> 节点。
2. 大部分元素节点都有子节点。比方说,<head> 节点有一个子节点:<title> 节点。<title> 节点也有一个子节点:文本节点 "DOM Tutorial"。
3. 当节点分享同一个父节点时,它们就是同辈(同级节点)。比方说,<h1> 和 <p>是同辈,因为它们的父节点均是 <body> 节点。
4. 节点也可以拥有后代,后代指某个节点的所有子节点,或者这些子节点的子节点,以此类推。比方说,所有的文本节点都是 <html>节点的后代,而第一个文本节点是 <head> 节点的后代。
5. 节点也可以拥有先辈。先辈是某个节点的父节点,或者父节点的父节点,以此类推。比方说,所有的文本节点都可把 <html> 节点作为先辈节点。
-->
注意:
- 只有一个根节点document
- 除了根节点外,其他所有节点都有唯一的一个父节点
- document是window对象的属性
- 元素的属性/文本/注释也是独立节点,注意属性节点 不是元素节点的子节点 二、获取元素的方式
1、旧方法 --- html4
(1)document.getElementById根据ID获取 最快
const boxtest1 = document.getElementById('div1');
console.log(boxtest1);
console.log(div1); // 注意:不建议直接用id获取元素
(2)document.getElementsByClassName 根据类名获取多个,取某一个值加[下标] HTMLCollection
const boxtest2 = document.getElementsByClassName('box1');
console.log(boxtest2);
boxtest2.forEach((i) => {
console.log(i);
}) //boxtest2.forEach is not a function
问:HTMLCollection没有forEach方法可以遍历吗???????????
答:可以。
注意:NodeList有forEach方法 也可以用for
for(let i = 0; i < boxtest2.length; i++) {
console.log(boxtest2[i]);
}
据标签名获取 多个 取某一个值加[下标] NodeList
const boxtest3 = document.getElementsByTagName('div');
console.log(boxtest3);
console.log(boxtest3[0]);
据标签的name属性获取 NodeList 多个 通过下标获取某一个节点
const boxtest4 = document.getElementsByName('www');
console.log(boxtest4[1]);
2、 H5新方法—参数是选择器
const boxtest5 = document.querySelector('div'); // 单个 满足条件的第一个
console.log(boxtest5);
const boxtest6 = document.querySelectorAll('div'); // 多个 满足条件的集合 NodeList [下标]获取某一个节点
console.log(boxtest6);
三、链式获取元素
1、获取父元素(元素节点对象) 再通过父元素获取子元素
const son1 = document.getElementsByTagName('div')[0].getElementsByClassName('son')[0];
console.log(son1);
const son2 = document.getElementsByClassName('fa')[0].getElementsByTagName('div')[0];
console.log(son2);
onst son3 = document.getElementsByClassName('fa')[0].getElementsByName('nametest')[0];
console.log(son3); // 报错
const son4 = document.getElementsByTagName('div')[0].getElementById('boxson');
console.log(son4); // 报错
const son5 = document.getElementsByName('uuu')[0].getElementsByTagName('div')[0];
console.log(son5);
(1) 获取多个时,哪怕满足条件的只有一个元素,返回也是一个集合
const son1 = document.getElementsByTagName('div');
(2) 获取多个时,满足条件的都能被获取到
const son1 = document.getElementsByClassName('a');
console.log(son1);
总结:getElementsByName getElementById不能在元素节点上调用
四、系统提供的直接获取元素的方法
<form action=""></form>
<form action=""></form>
<img src="" alt="">
<img src="" alt="">
<a href=""></a>
console.log(document.body); // body元素
console.log(document.forms); // form表单
console.log(document.images); // img元素
console.log(document.links); // a标签
console.log(document.URL); // 地址
console.log(document.documentElement); // 根节点
console.log(document.all); // 所有的元素节点
// console.dir(document);
console.log(document.getElementsByTagName("*"));
console.log(document.querySelectorAll("*"));
五、关系获取元素
HTML:
<div class="content">
<div class="sn0"></div>
333
<div class="sn1">
<p>2222</p>
</div>
999
<img src="" alt="" class="img1">
<img src="" alt="">
<div class="sn2"></div>
</div>
<div class="header_Img">
sss
<div class="header_txt">sss</div>
<div class="header_nickname"></div>
666
</div>
<ul>
<li>选项1</li>
<li>选项2</li>
<li>选项3</li>
<li>选项4</li>
<li>选项5</li>
</ul>
// 子级找父级
const header_txt = document.getElementsByClassName('header_txt')[0];
console.log(header_txt.parentElement); // 父元素
console.log(header_txt.parentNode); // 父节点
// 父级找子级
const header_Img = document.getElementsByClassName('header_Img')[0];
console.log(header_Img.children); // 子元素们(元素节点)
console.log(header_Img.childNodes); // 子节点们(所有节点)
console.log(header_Img.firstElementChild); // 第一个子元素
console.log(header_Img.firstChild); // 第一个子节点
console.log(header_Img.lastElementChild); // 最后一个子元素(跳过其他节点, 找元素节点)
console.log(header_Img.lastChild); // 最后一个子节点(不跳过其他类型节点)
// 兄弟
const sn1 = document.querySelector('.sn1');
console.log(sn1.nextElementSibling); // 下一个元素
console.log(sn1.nextSibling); // 下一个节点
console.log(sn1.previousElementSibling); // 上一个元素
console.log(sn1.previousSibling); // 上一个节点
练习1:通过.content找到p
const content = document.querySelector('.content');
// console.log(content.children[1].children[0]);
// console.log(content.children[1].firstElementChild);
// console.log(content.children[1].lastElementChild);
// console.log(content.firstElementChild.nextElementSibling.firstElementChild);
console.log(content.firstElementChild.nextElementSibling.lastElementChild);
练习2:通过li找到body
// const li0 = document.querySelector('li');
const li0 = document.querySelectorAll('li')[0];
// console.log(li0.parentElement.parentElement);
// console.log(li0.parentNode.parentNode);
console.log(li0.parentNode.previousElementSibling.parentNode);
console.log(li0.parentNode.previousElementSibling.lastElementChild);
六、节点的创建、添加、删除
1、创建节点
const div1 = document.createElement('div');
const div2 = document.createElement('div');
2、添加节点
(1)append 与 appendChild (在父元素添加子节点)
document.body.appendChild(div1);
document.body.append(div1);
append appendChild区别
1. append可以添加文本节点 appendChild只接受节点对象
document.body.append('这是txt');
document.body.appendChild('这是txt');
2. append可以一次性添加多个节点 appendChild不可以
document.body.append('这是txt1', '这是text2', div1);
document.body.appendChild(div1, div2);
3. append没有返回值 appendChild返回值为添加的对象
console.log(document.body.appendChild(div1));
console.log(document.body.append(div1));
(2)添加节点 insertBefore(要添加的节点, 要在哪个元素之前添加)
document.body.insertBefore(div2, document.getElementById('divs'));
3、克隆节点
el.cloneNode(); 参数:true/false true:包含子节点 false:不包含 默认false
(1)克隆html中已存在的id为divs的div节点 静态的
var res = document.getElementById('divs').cloneNode(true);
console.log(res);
document.body.append(res);
(2)克隆自己创建的节点
const p1 = document.createElement('p');
var res1 = p1.cloneNode();
document.body.append(res1);
4、向自己创建的节点中添加节点
const div1 = document.createElement('div');
const p2 = document.createElement('p');
div1.appendChild(p2);
document.querySelector('.son').appendChild(div1);
5、创建文本节点(了解)
创建一行文字,文本节点,创建一个div元素,将文本节点放入div中,再将div放到body中
const txt = document.createTextNode('文本节点'); // 文本节点对象
const div = document.createElement('div'); // 元素节点对象
//div.append(txt);
div.appendChild(txt);
document.body.append(div);
console.log(typeof txt);
// console.log(document.body.innerHTML);
// console.log(typeof document.body.innerHTML);
// document.body.innerHTML += '这是拼接上的字符串';
document.body.innerHTML += '<div>这是拼接上的字符串</div>';
6、节点删除
通过父元素删除子元素
document.getElementById('divs').removeChild(document.getElementsByClassName('son1')[0]);
const fa = document.getElementById('divs');
fa.removeChild(fa.firstElementChild);
通过元素自己直接删除
document.getElementsByClassName('son1')[0].remove();
替换元素(了解)
const p1 = document.createElement('p');
fa.replaceChild(p1, document.getElementsByClassName('son1')[0]);
七、节点内容的增删查改
HTML:
<div class="content">
如果
<div class="left">left-content</div>
<div class="right">
right-content
<div class="right-top">
right-top
</div>
</div>
if
</div>
<div class="data">
<div class="">0</div>
</div>
JavaScript:
// 1. 节点内容的获取 - 查找
console.log(document.querySelector('.content').innerHTML);
console.log(document.querySelector('.content').innerText);
// 2. 新增
// document.querySelector('.content').innerHTML += '<p>新增文本</p>';
document.querySelector('.content').innerText += '<p>innerText-新增</p>';
// 3. 修改
// document.querySelector('.content').innerHTML = '<div>www</div>';
// document.querySelector('.content').innerText = '<div>www</div>';
// 4. 删除/ 清空
// document.querySelector('.content').innerHTML = '';
document.querySelector('.content').innerText = '';
// 5. innerHTML innerText的区别
// a. innerHTML获取的是标签之间的所有内容 innerText只获取标签(包括子元素)之间的文本内容
// b. innerHTML里面写标签的字符串 可以被识别为标签, innerText里面写标签字符串 识别为字符串
// c. innerHTML+=赋值 可以拼接字符串和标签 但是innerText+= 会将标签原有的元素过滤掉
// 注意:innerHTML innerText 都是字符串
将后端的数据显示到页面上
var sss = [1, 2, 3, 4];
var str = '';
for(var i = 0; i < sss.length; i++) {
str += `<div>${sss[i]}</div>`; // undefined<div>1</div> + <div>2</div>
}
console.log(str);
// var sss1 = `<div>${sss[0]}</div>
// <div>${sss[1]}</div>
// <div>${sss[2]}</div>
// <div>${sss[3]}</div>`;
// console.log(sss1);
document.getElementsByClassName('data')[0].innerHTML += str;
var w; // undefined
var str = 'lll';
console.log(w + str); // 进行字符串的拼接 undefinedlll
八、节点的标准属性的增删查改
HTML:
<div class="box1" id="div1" style="color: red;">这是div标签</div>
<input type="text" value="999" name="username">
<br><br>
<input type="password" name="password" id="" value="123456">
<br><br>
<input type="radio" name="sex" id="" value="1" checked>
<br><br>
<input type="checkbox" name="hobby" id="" value="2" checked>
<br><br>
<img src="./imgs/baidu.png" alt="">
JavaScript:
// 获取
const div1 = document.querySelector('#div1');
console.log(div1.id, div1.style);
// 驼峰命名
const input1 = document.querySelectorAll('input');
console.log(input1[0].value);
console.log(input1[1].value);
console.log(input1[2].value);
console.log(input1[3].value);
// {username: '999', password: '123456', sex: 1, hobby: [1, 2, 3]}
console.log(input1[2].checked);
console.log(input1[3].checked);
const imgwww = document.querySelector('img');
console.log(imgwww.src);
// 修改
// imgwww.src = './imgs/baidu1.png';
// 新增
div1.style.backgroundColor = 'red';
// 删除
div1.style.backgroundColor = '';
待续......