1、DOM对象介绍
(1)什么是DOM
DOM:Document Object Model,文档对象模型。
作用:是一套规范文档内容的通用型标准。
(2)DOM HTML节点树
DOM HTML指的是DOM中为操作HTML文档提供的属性和方法。
文档(Document)表示HTML文件。
文档中的标签称为元素(Element)。
文档中的所有内容称为节点(Node)。
因此,一个HTML文件可以看作是所有元素组成的一个节点树,各元素节点之间有级别的划分 。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试</title>
</head>
<body>
<a href="#">链接</a>
<p>段落...</p>
</body>
</html>
HTML文档根据节点作用,分为标签节点、文本节点、属性节点和注释节点。
各节点之间的关系,又可分为以下几个方面:
a、根节点:标签是整个文档的根节点,有且仅由一个。
b、子节点:指的是某一个节点的下级节点。
c、父节点:指的是某一个节点的上级节点。
d、兄弟节点:两个节点同属于一个父节点。
(3)DOM对象的继承关系
<div id="test"></div>
<script>
var test = document.getElementById('test');
console.log(test); // 输出结果:<div id="test"></div>
console.log(test.__proto__); // 输出结果:HTMLDivElement { …… }
</script>
总结
document和Element是两种不同类型的节点(Node)对象。
它们不仅能够使用Node对象的一系列属性和方法完成节点操作。
也可以使用特有的属性和方法完成不同类型节点的操作。
<div id="test"></div>
<script>
var test = document.getElementById('test');
console.log(test.nodeName); // 通过节点方式获取节点名,输出结果:DIV
console.log(test.tagName); // 通过元素方式获取标签名,输出结果:DIV
console.log(document.nodeName); // document属于节点,输出结果:#document
console.log(document.tagName); // document不属于元素,输出结果:undefined
</script>
除了document和Element对象,还有其他几种类型的节点对象也继承Node对象,如文本(Text)、注释(Comment)等。
<script>
var test = document.getElementById('test');
test.nodeType === Node.ELEMENT_NODE; // 比较结果:true
document.nodeType === Node.DOCUMENT_NODE; // 比较结果:true
<script>
注意:DOM与document的关系
当浏览器下载到一个网页,通常是 HTML,这个 HTML 就叫 document(当然,这也是 DOM 树中的一个 node),document 通常是整个 DOM 树的根节点。这个 document 包含了标题(document.title)、URL(document.URL)等属性,可以直接在 JS 中访问到。
在一个浏览器窗口中可能有多个 document,例如,通过 iframe 加载的页面,每一个都是一个 document。
在 JS 中,可以通过 document 访问其子节点(其实任何节点都可以),如
document.body;document.getElementById(‘xxx’);
2、HTML元素操作
(1)获取操作的元素
a、通过document对象的方法和属性
document对象提供了一些用于查找元素的方法,利用这些方法可以根据元素的id、name和class属性以及标签名称的方式获取操作的元素。
<ul id="ul">
<li>PHP</li><li>JavaScript</li>
<ul><li>jQuery</li><ul>
</ul>
<script>
var lis = document.getElementById('ul').getElementsByTagName('li');
console.log(lis); // 输出结果:(3) [li, li, li]
</script>
<script>
var lis = document.getElementById('ul').children;
console.log(lis); // 输出结果:(3) [li, li, ul]
</script>
<li id="test" name="test">test</li>
<script>
var lis1 = document.getElementsByTagName('li'); // 获取标签名为li的对象集合
var test = document.getElementById('test'); // 获取id为test的li元素对象
console.log(lis1.test === test); // 比较结果:true
var lis2 = document.getElementsByName('test'); // 获取name名为test的对象集合
console.log(lis1.test === lis2[0]); // 比较结果:true
</script>
除了document.getElementById()方法返回的是拥有指定id的元素外,其他方法返回的都是符合要求的一个集合。若要获取其中一个对象,可以通过下标的方式获取,默认从0开始。
document对象提供一些属性,可用于获取文档中的元素。例如,获取所有表单标签、图片标签等。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
var body = document.getElementsByTagName('body')[0]; // 获取body元素
var html = document.getElementsByTagName('html')[0]; // 获取html元素
console.log(document.body === body); // 比较返回结果,输出结果:true
console.log(document.documentElement === html); // 比较返回结果,输出结果:true
</script>
</body>
</html>
document对象的body属性用于返回body元素。
document对象的documentElement属性用于返回HTML文档的根节点html元素。
注意:
通过document对象的方法与document对象的属性获取的操作元素表示的都是同一对象。如document.getElementsByTagName(‘body’)[0]与document.body全等。
HTML5新增的document对象方法
HTML5中为更方便获取操作的元素,为document对象新增了两个方法,分别为querySelector()和querySelectorAll()。
a、querySelector()方法用于返回文档中匹配到指定的元素或CSS选择器的第1个对象的引用。
b、querySelectorAll()方法用于返回文档中匹配到指定的元素或CSS选择器的对象集合。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>获取操作的元素</title>
</head>
<body>
<div id="box">box</div>
<div class="bar">bar</div>
<div name="main">main</div>
<script>
console.log(document.getElementById('box')); // 获取id为box的元素
console.log(document.getElementsByClassName('bar')); // 获取所有class为bar的元素
console.log(document.getElementsByTagName('div')); // 获取所有标签为div的元素
console.log(document.getElementsByName('main')); // 获取所有name为main的元素
</script>
<script>
var box = document.getElementById('box'); // 根据id获取元素对象
var divs = document.getElementsByTagName('div'); // 根据标签名获取对象集合
console.log(divs[0] === box); // 输出结果:true
</script>
<script>
console.log(document.querySelector('div')); // 获取匹配到的第1个div
console.log(document.querySelector('#box')); // 获取id为box的第1个div
console.log(document.querySelector('.bar')); // 获取class为bar的第1个div
console.log(document.querySelector('div[name]')); // 获取含有name属性的第1个div
console.log(document.querySelector('div.bar')); // 获取文档中class为bar的第1个div
console.log(document.querySelector('div#box')); // 获取文档中id为box的第1个div
</script>
</body>
</html>
元素对象提供了children属性用来获取指定元素的子元素
<body>
<ul id="ul">
<li>PHP</li><li>JavaScript</li>
<ul><li>jQuery</li><ul>
</ul>
</body>
<script>
var lis = document.getElementById('ul').children;
console.log(lis); // 输出结果:(3) [li, li, ul]
</script>
元素对象的children属性返回的也是对象集合,若要获取其中一个对象,也需通过下标的方式获取,默认从0开始。
另外,document对象中也有children属性,它的第一个子元素通常是html元素。
(2)元素内容
JavaScript中,若要对获取的元素内容进行操作,则可以利用DOM提供的属性和方法实现。
属性属于Element对象,方法属于document对象。
innerHTML在使用时会保持编写的格式以及标签样式。
innerText则是去掉所有格式以及标签的纯文本内容。
textContent属性在去掉标签后会保留文本格式。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>元素内容操作</title>
</head>
<body>
<div id="box">
The first paragraph...
<p>
The second paragraph...
<a href="http://www.example.com">third</a>
</p>
</div>
<script>
var box = document.getElementById('box');
console.log(box.innerHTML);
console.log(box.innerText);
console.log(box.textContent);
</script>
</body>
</html>
注意:
innerText属性在使用时可能会出现浏览器兼容的问题。因此,推荐在
开发时尽可能的使用innerHTML获取或设置元素的文本内容。同时,innerHTML属性和document.write()方法在设置内容时有一定的区别,前者作用于指定的元素,后者则是重构整个HTML文档页面。因此,读者在开发中要根据实际的需要选择合适的实现方式
案例:改变盒子大小
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
.box{width:50px;height:50px;background:#eee;margin:0 auto;}
</style>
</head>
<body>
<div id="box" class="box"></div>
<script>
var box = document.getElementById('box');
var i = 0; // 保存用户单击盒子的次数
box.onclick = function() { // 处理盒子的单击事件
++i;
if (i % 2) { // 单击次数为奇数,变大
this.style.width = '200px';
this.style.height = '200px';
this.innerHTML = '大';
} else { // 单击次数为偶数,变小
this.style.width = '50px';
this.style.height = '50px';
this.innerHTML = '小';
}
};
</script>
</body>
</html>
(3)元素属性
在DOM中,为了方便JavaScript获取、修改和遍历指定HTML元素的相关属性,提供了操作的属性和方法。
利用attributes属性可以获取一个HTML元素的所有属性,以及所有属性的个数length。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>元素属性操作</title>
<style>
.gray{background: #CCC;}
#thick{font-weight: bolder;}
</style>
</head>
<body>
<div>test word.</div>
<script>
// 获取div元素
var ele = document.getElementsByTagName('div')[0];
// ① 输出当前ele的属性个数
console.log('未操作前属性个数:' + ele.attributes.length);
// ② 为ele添加属性,并查看属性个数
ele.setAttribute('align', 'center');
ele.setAttribute('title', '测试文字');
ele.setAttribute('class', 'gray');
ele.setAttribute('id', 'thick');
ele.setAttribute('style', 'font-size:24px;border:1px solid green;');
console.log('添加属性后的属性个数:' + ele.attributes.length);
// ③ 获取ele的style属性值
console.log('获取style属性值:' + ele.getAttribute('style'));
// ④ 删除ele的style属性,并查看剩余属性情况
ele.removeAttribute('style');
console.log('查看所有属性:');
for (var i = 0; i < ele.attributes.length; ++i) {
console.log(ele.attributes[i]);
}
</script>
</body>
</html>
(4)元素样式
回顾:通过元素属性的操作修改样式。
元素样式语法:style.属性名称。
要求:需要去掉CSS样式名里的中横线“-”,并将第二个英文首字母大写。
举例:设置背景颜色的background-color,在style属性操作中,需要修改为backgroundColor。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="box"></div>
<script>
var ele = document.getElementById('box'); // 获取元素对象
ele.style.width = '100px';
ele.style.height = '100px';
ele.style.backgroundColor = 'red';
ele.style.transform = 'rotate(7deg)';
</script>
</body>
</html>
注意:
CSS中的float样式与JavaScript的保留字冲突,在解决方案上不同的浏览器
存在分歧。例如IE911、Chrome、FireFox可以使用“float”和“cssFloat”,Safari浏览器使用“float”,IE68则使用“styleFloat”。
问题:一个元素的类选择器可以有多个,在开发中如何对选择器列表进行操作?
原来的解决方案:利用元素对象的className属性获取,获取的结果是字符型,然后再根据实际情况对字符串进行处理。
HTML5提供的办法:新增的classList(只读)元素的类选择器列表。
举例:若一个div元素的class值为“box header navlist title”,如何删除header?
HTML5解决方案:div元素对象.classList.toggle(“header”);
除此之外,classList属性还提供了许多其他相关操作的方法和属性。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>classList的使用</title>
<style>
.bg{background:#ccc;}
.strong{font-size:24px;color:red;}
.smooth{height:30px;width:120px;border-radius:10px;}
</style>
</head>
<body>
<ul>
<li>PHP</li>
<li class="bg">JavaScript</li>
<li>C++</li>
<li>Java</li>
</ul>
<script>
// 获取第2个li元素
var ele = document.getElementsByTagName('li')[1];
// 若li元素中没有strong类,则添加
if (!ele.classList.contains('strong')) {
ele.classList.add('strong');
}
// 若li元素中没有smooth类,则添加;若有删除
ele.classList.toggle('smooth');
console.log('添加与切换样式后:');
console.log(ele);
</script>
<script>
ele.classList.remove('bg');
console.log('删除后:');
console.log(ele);
</script>
</body>
</html>
3、DOM节点操作
(1)获取节点
由于HTML文档可以看做是一个节点树,因此,可以利用操作节点的方式操作HTML中的元素。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
// 访问document节点的第1个子节点
console.log(document.firstChild); // 访问结果:<!DOCTYPE html>
// 访问document节点的第2个子节点
console.log(document.firstChild.nextSibling); // 访问结果:<html>……</html>
</script>
</body>
</html>
注意:
childNodes属性与前面学习过的children属性的区别。
相同点:都可以获取某元素的子元素。
不同点: childNodes属性用于节点操作,返回值中还会包括文本节点等其他类型的节点,是一个NodeList对象的集合。 children属性用于元素操作,返回的是HTMLCollection对象的集合
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>节点操作</title>
</head>
<body>
<ul id="ul">
<li>JS</li>
<li>BOM</li>
<li>DOM</li>
<!--注释-->
</ul>
<script>
var ul = document.getElementById('ul'); // 根据id获取ul的元素对象
console.log(ul.childNodes); // 查看ul下的所有节点
</script>
</body>
</html>
(2)节点追加
在获取元素的节点后,还可以利用DOM提供的方法实现节点的添加。
create系列的方法是由document对象提供的,与Node对象无关。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>节点追加</title>
</head>
<body>
<script>
var h2 = document.createElement('h2'); // 创建h2元素节点
var text = document.createTextNode('Hello JavaScript'); // 创建文本节点
var attr = document.createAttribute('align'); // 创建属性节点
attr.value = 'center'; // 为属性节点赋值
h2.setAttributeNode(attr); // 为h2元素添加属性节点
h2.appendChild(text); // 为h2元素添加文本节点
document.body.appendChild(h2); // 将h2节点追加为body元素的子节点
console.log(document.getElementsByTagName('h2')[0]);
</script>
</body>
</html>
(3)节点删除
语法:removeChild()和removeAttributeNode()方法实现。
返回值:是被移出的元素节点或属性节点。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>删除节点和节点属性</title>
</head>
<body>
<ul>
<li>PHP</li><li>JavaScript</li><li class="strong">UI</li>
</ul>
<script>
var child = document.getElementsByTagName('li')[2]; // 获取第3个li元素
var attr = child.getAttributeNode('class'); // 获取元素的class属性值
console.log(child.removeAttributeNode(attr)); // 删除元素的class属性值
console.log(child.parentNode.removeChild(child)); // 删除元素
</script>
</body>
</html>
案例:列表的增删和移动
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>列表的增删和移动</title>
<style>
body{background:#ddd;text-align:center}
.list{display:inline-block;margin-top:20px;padding:40px;border-radius:8px;background:#fff;color:#333;text-align:left;font-size:13px}
.list-ul{list-style:none;margin:0;padding:0}
.list-option{padding:6px 0;}
.list-input{width:300px;border:1px solid #ccc;padding:4px;font-size:14px;color:#333}
.list-input:hover{background:#effaff}
.list-btn span{color:#0065A0;;cursor:pointer}
.list-btn span:hover{text-decoration:underline}
.list-btn b{text-align:center;background-color:#D6EDFF;border-radius:6px;width:20px;height:20px;display:inline-block;margin:0 2px;cursor:pointer;color:#238FCE;border:1px solid #B3DBF8;float:left}
.list-bottom{margin-top:5px}
.list-add-show{color:#f60;cursor:pointer}
.list-add-show:before{position:relative;top:1px;margin-right:5px;content:"+";font-weight:700;font-size:16px;font-family:arial}
.list-add-show span:hover{text-decoration:underline}
.list-add-area{margin-top:5px}
.list-add-add{cursor:pointer;margin-left:5px}
.list-add-cancel{cursor:pointer;margin-left:4px}
.list-add-input{width:180px;border:1px solid #ccc;padding:4px;font-size:14px;color:#333}
.list-add-input:hover{background:#effaff}
.list-tmp{display:none}
.list-hide{display:none}
</style>
</head>
<body>
<form>
<div class="list">
<ul class="list-ul">
<li class="list-option">
<input class="list-input" type="text" name="list[]">
<span class="list-btn">
<span class="list-up">[上移]</span>
<span class="list-down">[下移]</span>
<span class="list-del">[删除]</span>
</span>
</li>
</ul>
<div class="list-bottom">
<span class="list-add-show"><span>添加项目</span></span>
<div class="list-add-area list-hide">
添加到列表:
<input class="list-add-input" type="text" name="list[]">
<input class="list-add-add" type="button" value="添加">
<input class="list-add-cancel" type="button" value="取消">
</div>
</div>
</div>
</form>
<script src="SmartList.js"></script>
<script>
SmartList('list', ['PHP', 'JavaScript']);
</script>
</body>
</html>