导读一:什么是DOM
DOM中的三个字母,D(文档)可以理解为整个Web加载的网页文档;O(对象)可以理解为类似window对象之类的东西,可以调用属性和方法,这里我们说的是document对象;M(模型)可以理解为网页文档的树型结构
导读二:DOM树
1.DOM树把文档映射成树形结构,通过节点对象对其处理,处理的结果可以加入到当前的页面。 文档:一个页面就是一个文档,DOM中使用document表示。 节点:网页中的所有内容,在文档树中都是节点(标签、属性、文本、注释等),使用node表示
2.根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:
1.文档节点:整个文档是一个文档节点
2.标签节点:网页中的每个标签(也即每个 HTML 元素)是标签节点
3.属性节点:每个 HTML 属性是属性节点
4.文本节点:HTML 元素内的文本是文本节点
5.注释节点:注释是注释节点
3. DOM 树中的所有节点均可通过 JavaScript 进行访问, 所有 HTML 元素(节点)均可被修改,也可以创建或删除
4.DOM把以上内容都看作是对象
5.我们在实际开发中,节点操作主要操作的是元素节点
一.操作元素
1.获取元素
a.根据id获取元素
语法:document.getElementById(id)
参数:id值,区分大小写的字符串
b.根据标签名获取元素
语法:document.getElementsByTagName('标签名')
参数:标签名
c.根据类名获取元素
语法:document.getElementsByClassName('类名')
参数:类名,class的属性值
d.根据指定选择器获取所有元素(H5新增)
语法:document.querySelectorAll('选择器')
参数:选择器,选择器要加符号,比如'#nav'
e.根据指定选择器获取第一个元素(H5新增),个人比较喜欢
语法:document.querySelector('选择器')
参数:选择器,选择器要加符号,比如'#nav'
f.获取特殊元素(body,html)
document.body:返回body元素对象
document.documentElement:返回html元素对象
<script type="text/javascript">
var h1 = document.getElementById('h1')
console.log(h1); // <h1 id="h1">我是h1标题</h1>
var h2 = document.getElementsByClassName('h2')
console.log(h2); // HTMLCollection [h2.h2]
var span = document.getElementsByTagName('span')
console.log(span); // HTMLCollection [span]
var ul = document.querySelector('#ul')
console.log(ul); // <ul id="ul">…</ul>
var li = document.querySelectorAll('li')
console.log(li); // NodeList(5) [li, li, li, li, li]
// 遍历的方法打印
for(var i = 0;i < li.length;i++){
console.log(li[i]);
}
</script>
2.改变元素的内容
a.innerHTML与innerText的区别
1.获取内容时
innerHTML获取的是从对象的起始位置到终止位置的全部内容,保留空格和换行
innerText获取的是从对象的起始位置到终止位置的内容,但它的 空格和换行也会去掉
2.设置内容时
innerHTML会识别HTML标签。前后空格和换行都保留
innerText不会识别HTML标签(会把HTML标签当做一个普通的文本)。前后空格和换行都保留
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<p></p>
<p class="p"></p>
</body>
<script type="text/javascript">
//改变元素时
var p1 = document.querySelector('p');
p1.innerHTML = '<em>我是要成为海贼王的男人</em>'; //我是要成为海贼王的男人
var p2 = document.querySelector('.p');
p2.innerText = '<em>我是要成为海贼王的男人</em>'; //<em>我是要成为海贼王的男人</em>
</script>
</html>
b.表单元素的属性操作
表单元素:<input>元素、<select>元素、<option>元素、<textarea>元素。
常见属性列举:type、disabled、checked、selected、readOnly
注:disabled、checked、selected这些属性的值是布尔型
<body>
<button type="button" onclick="javascript:first();">文本框</button>
<input type="text" name="" id="ipt" value="中华" />
<br>
<button type="button" onclick="javascript:sec();">选项框</button>
<select name="city" id="select">
<option value="0" >请选择</option>
<option value="1" selected>北京</option>
<option value="2" id="sh">上海</option>
<option value="3" >深圳</option>
<option value="4">广州</option>
</select>
<br>
<button type="button" onclick="javascript:third();">文本域</button>
<textarea rows="1" cols="25" id="textarea" style="resize: none;">我是好人</textarea>
</body>
<script type="text/javascript">
function first() {
console.log(document.querySelector('#ipt').type);
/* document.querySelector('#ipt').type = 'password'; */
/* document.querySelector('#ipt').type = 'submit'; */
console.log(document.querySelector('#ipt').disabled);
/* document.querySelector('#ipt').disabled = 'true'; */
}
function sec() {
// 获得第一个,第一个被选中,返回true,凡是false;
console.log(document.querySelector('option').selected);
// 让第一个被选中
/* document.querySelector('option').selected = 'true'; */
console.log(document.querySelector('#sh').disabled);
//上海选项被禁用
document.querySelector('#sh').disabled = 'true';
console.log(document.querySelector('#select').disabled);
/* document.querySelector('#select').disabled = 'true'; */
}
function third() {
console.log(document.querySelector('#textarea').disabled);
/* document.querySelector('#textarea').disabled = 'true'; */
console.log(document.querySelector('#textarea').readOnly);
document.querySelector('#textarea').readOnly = 'true';
// 点击按钮,返回false,false,然后变成只读,不能对内容修改
// 当 disabled = true;时,为禁用,不能对表单元素操作
// 当 readonly = true;时,为只读,不能更改表单里的内容
}
</script>
案例:密码的明文与密文之间的切换
原理:当点击按钮时,input的text属性变为password属性,再次点击返回原来的值
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>练习_密码的明文与密文之间的切换</title>
<style>
.box {
position: relative;
width: 400px;
border-bottom: 1px solid #ccc;
margin: 100px auto;
}
.box input {
width: 370px;
height: 30px;
border: 0;
outline: none;
}
.box img {
position: absolute;
top: 2px;
right: 2px;
width: 24px;
}
</style>
<script type="text/javascript">
function firstFunc() {
/* 在此处编写实现逻辑 */
/* 获取元素 */
var img = document.querySelector('#imgId')
var ipt = document.querySelector('#pwdId')
/* 绑定事件 */
if(ipt.type == 'password'){
img.src = 'img/open.png';
ipt.type = 'text';
} else {
img.src = 'img/close.png';
ipt.type = 'password';
}
}
</script>
</head>
<body>
<div class="box">
<img src="img/close.png" alt="" id="imgId" onclick="javascript:firstFunc()">
<input type="password" name="" id="pwdId">
</div>
</body>
</html>
c.元素样式的属性操作
通过js修改元素的大小,颜色,位置灯样式
1.通过style属性操作:适合样式较少的情况
2.通过className属性操作:会更改元素类名,覆盖之前的类名
注:使用style设置的样式 > className设置的样式
此案例能够解释使用过style更改样式,不能用className更改,反之则可以
<style type="text/css">
p{
background-color: orange;
color: white;
}
.change{
background-color: #CCCCCC;
color: black;
}
</style>
<script type="text/javascript">
function first(){
/* var p = document.querySelector('p').style; */
document.querySelector('p').style.backgroundColor = 'blue';
document.querySelector('p').style.color = 'red';
}
function sec(){
document.querySelector('p').className= 'change';
}
</script>
</head>
<body>
<p>这是一行文字</p>
<button type="button" onclick="javascript:first();">通过style属性操作</button>
<button type="button" onclick="javascript:sec();">通过classname操作</button>
</body>
练习:实现开关灯
<style type="text/css">
body{
background-color: #000000;
}
</style>
<script type="text/javascript">
function first(){
var btn = document.querySelector('#btn1')
var body = document.querySelector('body')
if(btn.innerHTML == '开灯'){
body.style.backgroundColor = '#FFFFFF';
btn.innerHTML = '关灯';
} else{
body.style.backgroundColor = '#000000';
btn.innerHTML = '开灯';
}
}
</script>
</head>
<body>
<button type="button" id="btn1" onclick="javascript:first();">开灯</button>
</body>
3.H5的自定义属性
自定义属性获取是通过getAttribute(‘属性’) 获取。但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。因此,HTML5中新增了自定义属性。HTML5中规定自定义属性的属性名以”data-“开头
a.内置属性
1.获取元素对象的属性值:元素对象.属性名 //不可用于获取自定义属性值
2.设置元素对象的属性值:元素对象.属性名 = 值 //也可用于设置自定义属性值
b.自定义属性
1.获取元素对象的自定义属性值:元素对象.getAttribute('属性名')
2.设置元素对象的自定义属性值:元素对象.setAttribute('属性名',值)
3.移除元素对象的自定义属性:元素对象.removeAttribute('属性名')
<script type="text/javascript">
function first(){
var div = document.querySelector('#box')
console.log(div.getAttribute('attr')); // 1
console.log(div.getAttribute('data-attr')); // one
console.log(div.getAttribute('data-list-name')); // ul
console.log(div.dataset.attr); // one
console.log(div.dataset.listName); // ul
console.log(div.dataset['attr']); // one
console.log(div.dataset['list-name']); // undefined
console.log(div.dataset['listName']); // ul
}
function sec(){
var div = document.querySelector('#box')
div.setAttribute('data-time',20)
console.log(div.getAttribute('data-time')); // 20
}
function third(){
var div = document.querySelector('#box')
console.log(div.dataset.attr); // 第一次返回 one,移除后返回undefined
div.removeAttribute('data-attr')
console.log(div.dataset.attr); // undefined
}
</script>
</head>
<body>
<div id="box" attr = '1' data-attr = 'one' data-list-name = 'ul'>
</div>
<button type="button" onclick="javascript:first();">获得h5的自定义值</button>
<button type="button" onclick="javascript:sec();">设置h5的自定义值</button>
<button type="button" onclick="javascript:third();">移除h5的自定义值</button>
</body>
二.操作节点
1.获取节点
属性名称 | 描述 |
parentNode | 返回节点的父节点 是最近的一个父节点,如果指定的节点没有父节点则返回null |
childNodes | 返回子节点集合。它返回所有的子节点,包括元素节点,文本节点 如果只想要获得里面的元素节点,则需要专门处理。故不提倡使用childNodes。里面的每一个节点表示为childNodes[i] |
firstChild | 返回第一个子节点。同样也是包含所有的节点。找不到则返回null 最普遍的用法是访问该元素的文本节点 |
lastChild | 返回最后一个子节点。同样也是包含所有的节点。找不到则返回null |
previousSibling | 返回上一个兄弟节点。包括元素节点,文本节点等。找不到则返回null |
nextSibling | 返回下一个兄弟节点。包括元素节点,文本节点等。找不到则返回null。 |
children | 返回子元素节点集合。它只返回子元素节点,其余节点(比如文本节点等)不返回 |
firstElementchild | 返回第一个子元素节点。 找不到则返回null (IE9 及其以上支持) |
lastElementchild | 返回最后一个子元素节点。找不到则返回null(IE9 及其以上支持) |
previousElementsibling | 返回上一个兄弟元素节点。找不到则返回null(IE9 及其以上支持) |
nextElementsibling | 返回下一个兄弟元素节点。找不到则返回null(IE9 及其以上支持) |
<script type="text/javascript">
function sec(){
var ul = document.querySelector('ul')
console.log(ul.children); // HTMLCollection(5) [li, li, li, li, li]
console.log(ul.children[0]); // <li>第一个子节点</li>
console.log(ul.children[1]); // <li>第二个子节点</li>
console.log(ul.children[ul.children.length - 1]); // <li>第五个子节点</li>
console.log(ul.firstElementChild); // <li>第一个子节点</li>
console.log(ul.lastElementChild); // <li>第五个子节点</li>
console.log(ul.firstElementChild.previousElementSibling); // null
console.log(ul.firstElementChild.nextElementSibling); // <li>第二个子节点</li>
console.log(ul.lastElementChild.previousElementSibling); // <li>第四个子节点</li>
console.log(ul.lastElementChild.nextElementSibling); // null
console.log(ul.firstElementChild.previousSibling); // 中国
console.log(ul.firstElementChild.nextSibling); // 安徽
}
</script>
</head>
<body>
<button type="button" onclick="javascript:sec()">子节点</button>
<ul id="ul">中国<li>第一个子节点</li>安徽
<li>第二个子节点</li>
<li>第三个子节点</li>
<li>第四个子节点</li>
<li>第五个子节点</li>
</ul>
</body>
2.创建/添加/删除/替换/复制节点
a.创建节点
语法:document.createElement('tagName')
b.添加节点
语法:node.appendChild(child) 新节点将作为父节点的最后一个子节点存在
node.insertBefore(child, refChild) 新节点将被插入到已存在的这个节点的前面
<script type="text/javascript">
function creat(){
/* 创建节点 */
var li = document.createElement('li')
li.innerHTML = '第一个列表项';
console.log(li);
/* 添加节点 */
var ul = document.querySelector('ul')
var newul = ul.appendChild(li)
console.log(newul);
console.log(ul);
/* 添加节点,到已有的节点之前 */
var lio = document.createElement('li')
lio.innerHTML = '最前面的列表项';
var li3 = ul.insertBefore(lio,ul.children[0])
console.log(ul);
}
</script>
</head>
<body>
<button type="button" onclick="javascript:creat();">创建和添加节点</button>
<ul>
<li>起初的列表项</li>
</ul>
</body>
c.删除节点
语法:node.removeChild(refChild) 从父节点中删除一个子节点
<script type="text/javascript">
function del() {
var ul = document.querySelector('ul')
var btn = document.querySelector('button')
if (ul.children.length == 0) {
btn.disabled = true;
} else {
ul.removeChild(ul.children[0])
}
}
</script>
<body>
<button type="button" onclick="javascript:del();">删除节点</button>
<ul>
<li>路飞</li>
<li>山治</li>
<li>索大</li>
<li>乌索普</li>
</ul>
</body>
d.替换节点
语法:node.replaceChild(newChild, oldChild) 用newChild节点替换node下的oldChild子节点
<script type="text/javascript">
function replace(){
var li = document.querySelector('ul').lastElementChild;
var newli = document.querySelector('ul').firstElementChild;
li.parentNode.replaceChild(newli,li)
var btn = document.querySelector('button')
btn.disabled = 'true';
}
</script>
</head>
<body>
<button type="button" onclick="javascript:replace();">替换节点</button>
<ul>
<li>路飞</li>
<li>妮可罗宾</li>
<li>山治</li>
<li>索大</li>
<li>乌索普</li>
<li>克洛克达尔</li>
</ul>
</body>
e.复制节点
语法:node.cloneNode(); 复制node节点
<script type="text/javascript">
function copy(){
var ul = document.querySelector('ul')
var li = ul.children[2].cloneNode(true)
ul.insertBefore(li,ul.children[0]); // 放在列表目标元素 ul.children[0] 之前
ul.appendChild(li) // 放在已有列表元素之后
}
</script>
</head>
<body>
<button type="button" onclick="javascript:copy();">复制节点</button>
<ul>
<li>路飞</li>
<li>山治</li>
<li>索大</li>
<li>乌索普</li>
</ul>
</body>
案例:发表留言并删除
<style type="text/css">
* {
margin: 0;
padding: 0;
}
a {
float: right;
text-decoration: none;
margin-right: 30px;
}
body {
padding: 100px;
}
textarea {
width: 200px;
height: 100px;
border: 1px solid pink;
outline: none;
resize: none;
}
ul {
margin-top: 50px;
}
li {
width: 300px;
padding: 5px;
background-color: rgb(245, 209, 243);
color: red;
font-size: 14px;
margin: 15px 0;
}
</style>
<script type="text/javascript">
// 发表留言和删除留言
function firstFunc() {
//获取元素
var text = document.querySelector('textarea')
var ul = document.querySelector('ul')
// 对输入的内容进行判断
if (text.value == '') {
alert('请输入内容');
} else {
var li = document.createElement('li')
// 增加元素节点
li.innerHTML = text.value + "<a href='javascript:;'>×</a>";
//输入的内容
ul.insertBefore(li, ul.children[0])
//新增加的内容放到最前面
text.value = '';
//发表后文本框中内容为空
}
// 删除节点
var del = document.querySelectorAll('a')
for(var i = 0;i < del.length;i++){
//遍历增加的元素
del[i].onclick = function(){
ul.removeChild(this.parentNode)
//删除当前那一行的节点
}
}
}
</script>
</head>
<body>
<textarea></textarea>
<button type="button" onclick="javascript:firstFunc()">发表评论</button>
<ul></ul>
</body>