排他思想,简单理解就是排除掉其他的(包括自己),然后再给自己设置想要实现的效果。总而言之,排他思想的实现步骤就是所有元素全部清除与设置当前元素。
【案例】设置一些按钮,当点某个按钮时,该按钮变色,其余不变。在同一组元素中,想要某一个元素实现某种样式,使用循环的排他思想算法来实现。
<!-- ①编写HTML结构体代码 --> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <!-- ②编写JS代码 --> <script> //1、获取所有按钮,btn得到了伪数组 var btn = document.getElementsByTagName("button"); //2、给每个button注册click事件 for (var i = 0; i < btn.length; i++) { btn[i].onclick = function () { //循环排他,将所有按钮的背景色去掉 for (var j = 0; j < btn.length; j++) { //不设置按钮的背景色 btn[j].style.backgroundColor = ""; } this.style.backgroundColor = "pink";//设置当前按钮的背景色为粉色 } } </script>
在DOM对象中可以使用“element.属性”的方式来获取内置的属性值,但是DOM对象并不能直接使用点语法获取到自定义属性的值,因此使用以下方法获取属性值:
对于元素(标签)的固有属性有两种方法:
元素名.固有属性 元素名.getAttribute("固有属性")
对于用户自定义的属性:
元素名.getAttribute("自定义属性")
示例:
<div id="demo" index="1" class="nav"></div> <script> //获取元素 var div = document.querySelector("div"); console.log("Id:", div.id);//元素名.固有属性 console.log("Id:", div.getAttribute("id")); console.log("index:", div.index);//index不是div的固有属性,因此输出undefined console.log("index:", div.getAttribute("index")); console.log("Class:", div.class);//class不是div的固有属性,因此输出undefined console.log("Class:", div.getAttribute("class")); </script>
在DOM对象中可以使用“element.属性= '值'
”的方式来设置内置的属性值,并且针对于自定义属性,提供了“element.setAttribute('属性', '值')
”的方式进行设置。
固有属性值的设置:
element.属性名 = "值" element.setAttribute("属性" ,"值")
用户自定义的属性值的设置:
element.setAttribute("属性" ,"值")
值得一提的是,设置了自定义属性的标签,在浏览器中的HTML结构中可以看到该属性。
示例:
<!-- 设置一个div,不进行任何操作 --> <div></div> <!-- 利用JavaScript代码设置其属性以及属性值 --> <script> //获取元素 var div = document.querySelector("div"); //方法1:设置id值为test div.setAttribute("id", "test"); //方法2:设置class为nav div.className = "nav"; //输出div console.log(div); </script>
可以看出属性被添加上去了
在DOM中使用“element.removeAttribute('属性')
”的方式来移除元素属性。接下来,通过案例演示如何移除属性值。
element.removeAttribute('属性')
示例:
<div id="d1" class="nav" index="1"></div> <script> //获取div元素 var div = document.querySelector("div"); //移除id属性 div.removeAttribute("id"); //移除index属性 div.removeAttribute("index"); //输出移除后的div元素 console.log("移除后的元素为:", div); </script>
一般的自定义属性可以通过getAttribute('属性')
方法来获取,但是有些自定义属性很容易引起歧义,不容易判断是元素的自带属性还是自定义属性。因此,HTML5新增了自定义属性的规范,在HTML5中规定通过“data-属性名
”的方式设置自定义属性。
元素的“ data-* ”自定义属性有两种设置方式,分别如下:
1、在HTML中设置自定义属性,语法为:
data-属性名
data-表示前缀,属性名是自己定义的属性名
示例:
<!-- 在div元素上设置data-index属性 --> <div data-index="1"></div>
2、在JavaScript中设置自定义属性
在JavaScript代码中,可以通过setAttribute('属性', 值)
或者“元素对象.dataset.属性名='值'
”两种方式设置自定义属性。需要注意的是,通过后者的方式只能设置以“data-”开头的自定义属性。语法为:
setAttribute('属性', 值) element.dataset.属性名='值'
示例:
<div></div> <script> var div = document.querySelector("div"); div.setAttribute("data-name", "d1"); div.dataset.index = "2"; console.log(div); </script>
在DOM操作中,提供了两种获取属性值的方式:
1、是过getAttribute()方式,该方式可以获取内置属性或者自定义属性。
语法为:
元素名.getAttribute("属性")
这种方法在前面已经举例说明,因此在这里不过多陈述。
2、使用HTML5新增的“element.dataset.属性”或者“element.dataset[‘属性’] ”方式(有兼容性问题)。
格式为:
element.dataset.属性名 element.dataset['属性名']
dataset:是一个集合,里面存放的是以“ data- ”开头的所有自定义属性。
示例:
<div data-index="2" data-name="橘猫吃不胖" data-class="d1"></div> <script> //获取元素 var div = document.querySelector("div"); //获取索引值 console.log("index:", div.dataset.index); //获取name属性 console.log("name:", div.dataset["name"]); //获取class属性 console.log("class:", div.dataset["class"]); </script>
若自定义属性名含有多个分隔符(-),在获取属性值时,需要去掉“-”,采用驼峰命名法。例如:
<P data-list-phone="12345678901"></P> <script> var p = document.querySelector("p"); console.log(p.dataset.listPhone); </script>
在获取list-phone属性时采用:p.dataset.listPhone方式。
HTML文档可以看作是一个节点树,网页中的所有内容都是节点,一般来说,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这3个基本属性。下面列举常见的节点类型:
节点 | 类型 |
---|---|
元素节点 | nodeType为1 |
属性节点 | nodeType为2 |
文本节点 | nodeType为3,文本节点包含文字、空格、换行等 |
一个HTML文件可以看作是所有元素组成的一个节点树,各元素节点之间有级别的划分。
DOM根据HTML中各节点的不同作用,可将其分别划分为标签节点(元素节点)、文本节点和属性节点。节点之间的层级关系如下:
节点 | 层级关系 |
---|---|
根节点 | <html> 标签是整个文档的根节点,有且仅有一个 |
父节点 | 指的是某一个节点的上级节点 |
子节点 | 指的是某一个节点的下级节点 |
兄弟节点 | 两个节点同属于一个父节点 |
1、获取父级节点
在JavaScript中,可以使用parentNode属性来获得离当前元素的最近的一个父节点,如果找不到父节点就返回为 null,语法格式为:
obj.parentNode
obj是一个DOM对象。
示例:
<div class="demo"> <div class="box"> <span class="child">span元素</span> </div> </div> <script> //获取元素 var child = document.querySelector(".child"); //输出离child元素最近的父级节点(box) console.log(child.parentNode); </script>
2、获取子级节点
在JavaScript中,可以使用childNodes属性或者children属性两种方式来获得当前元素的所有子节点的集合,语法格式为:
element.childNodes //获取所有的子节点(所有类型的子节点) element.children //获取子元素节点(推荐使用)
方式1:childNodes属性获得的是当前元素的所有子节点的集合,该集合为即时更新的集合。childNodes属性返回的是NodeList对象的集合,返回值里面包含了元素节点、文本节点等其他类型的节点。
示例:
<ul> <li>我是li</li> <li>我是li</li> <li>我是li</li> </ul> <script> var ul = document.querySelector("ul"); var lis = ul.querySelectorAll("li"); console.log(lis);//输出获取到的所有li元素 console.log("ul的子节点:", ul.childNodes); console.log("ul的第二个子节点:", ul.childNodes[1]); console.log("ul第2个子节点的类型:", ul.childNodes[1].nodeType);//元素节点 </script>
text代表了换行,因此ul的第二个子节点是第一个li元素。
方式2:children是一个可读的属性,返回所有子元素节点。children只返回子元素节点,其余节点不返回,目前各大浏览器都支持该属性,在实际开发中推荐使用children。
示例:
<ul> <li>我是li</li> <li>我是li</li> <li>我是li</li> </ul> <script> var ul = document.querySelector("ul"); var lis = ul.querySelectorAll("li"); console.log(lis);//输出获取到的所有li元素 console.log("ul的子节点:", ul.children); console.log("ul的第2个子节点:", ul.children[1]); console.log("ul第2个子节点的类型:", ul.children[1].nodeType);//元素节点 </script>
在本例中,ul的第二个子节点是第二个li元素。
childNodes属性与children属性虽然都可以获取某元素的子元素,但是两者之间有一定的区别。前者用于节点操作,返回值是NodeList对象集合,后者用于元素操作,返回的是HTMLCollection对象集合。
方式3:使用firstChild属性和lastChild属性获取子节点,前者返回第一个子节点,后者返回的是最后一个子节点,如果找不到则返回null。需要注意的是它们的返回值包括文本节点和元素节点等。
示例:
<ul> <li>我是li 1</li> <li>我是li 2</li> <li>我是li 3</li> </ul> <script> var ul = document.querySelector("ul"); console.log("ul的第一个子节点:", ul.firstChild); console.log("ul的最后一个子节点:", ul.lastChild); </script>
第一个和最后一个子节点都是换行。
方式4:使用firstElementChild属性和lastElementChild属性获取子元素节点,前者返回第一个子元素节点,后者返回最后一个子元素节点,如果找不到则返回null。需要注意的是,这两个属性有兼容性问题,IE9以上才支持。
示例:
<ul> <li>我是li 1</li> <li>我是li 2</li> <li>我是li 3</li> </ul> <script> var ul = document.querySelector("ul"); console.log("ul的第一个子节点:", ul.firstElementChild); console.log("ul的最后一个子节点:", ul.lastElementChild); </script>
实际开发中,firstChild 和lastChild 包含其他节点,操作不方便,而firstElementChild和lastElementChild又有兼容性问题,为了解决兼容性问题,在实际开发中通常使用“obj.children[索引] ”的方式来获取子元素节点。
3、获取兄弟节点
获取兄弟节点的方法如下:
属性 | 含义 |
---|---|
nextSibling | 获得下一个兄弟节点 |
previousSibling | 获得上一个兄弟节点 |
它们的返回值包含元素节点或者文本节点等。如果找不到,就返回null。
属性 | 含义 |
---|---|
nextElementSibling | 返回当前元素的下一个兄弟元素节点 |
previousElementSibling | 返回当前元素的上一个兄弟元素节点,如果找不到则返回null。 |
需要注意的是,这两个属性有兼容性问题,IE9以上才支持。
实际开发中,nextSibling和previousSibling属性返回值都包含其他节点,操作不方便,而nextElementSibling和previousElementSibling又有兼容性问题。为了解决兼容性问题,在实际开发中通常使用封装函数来处理兼容性。
示例:
<div>今天天气很好</div> <p>橘猫吃不胖</p> <span>每天都学前端</span> <script> //获取p标签 var p = document.querySelector("p"); console.log("p标签的上一个兄弟节点是:", p.previousSibling); console.log("p标签的下一个兄弟节点是:", p.nextSibling); console.log("p标签的上一个元素节点是:", p.previousElementSibling); console.log("p标签的下一个元素节点是:", p.nextElementSibling); </script>
注:#text是空格
在DOM中,使用document.createElement('tagName')
方法创建由tagName指定的HTML元素,也称为动态创建元素节点。
动态创建元素节点的3种常见方式如下:
方式 | 含义 |
---|---|
document.write() | 创建元素,如果页面文档流加载完毕,再调用会导致页面重绘 |
element.innerHTML | 将内容写入某个DOM节点,不会导致页面全部重绘 |
document.createElement() | 创建多个元素,结构清晰,效率稍微低一点,但是结构更加清晰 |
示例:
<script> document.write("<div>橘猫吃不胖</div>"); </script>
<div></div> <script> var div = document.querySelector("div"); var str = `<div> <h2>橘猫吃不胖</h2> <p>每天都学习</p> </div>` div.innerHTML = str; </script>
<script> var div = document.createElement("div"); div.className = "d1"; console.log(div); </script>
DOM中,提供了node.appendChild()和node.insertBefore()方法用于添加节点,node. removeChild(child)用于删除节点。
下面讲解这3种方法的使用。
方法 | 含义 |
---|---|
appendChild() | 将一个节点添加到指定父节点的子节点列表末尾 |
insertBefore(child, 指定元素) | 将一个节点添加到父节点的指定子节点前面 |
removeChild(child) | 用于删除节点,该方法从DOM中删除一个子节点,返回删除的节点 |
示例:
<div> <p>橘猫吃不胖</p> <p>我爱学习</p> </div> <script> //获取元素 var div = document.querySelector("div"); //创建一个p标签 var p = document.createElement("p"); //在我爱学习后添加新创建的p标签 div.appendChild(p); //输出该div console.log(div); </script>
<div> <p class="p1">橘猫吃不胖</p> </div> <script> //获取元素 var div = document.querySelector("div"); var p1 = document.querySelector(".p1"); //创建一个p标签作为要插入的节点 var p = document.createElement("p"); //在div前添加新创建的p标签 div.insertBefore(p, p1);//前面是被插入的节点,后面是要插在哪个节点的前面 //输出该div console.log(div); </script>
<div> <p class="p1">橘猫吃不胖</p> <p>我爱学习</p> </div> <script> //获取元素 var div = document.querySelector("div"); var p = document.querySelector(".p1"); //删除div下的第一个标签 div.removeChild(p); //输出div console.log(div); </script>
在DOM中,提供了node.cloneNode()方法,返回调用该方法的节点的一个副本,也称为克隆节点或者拷贝节点。语法为:
需要被复制的节点.cloneChild(true/false)
如果参数为空或false,则是浅拷贝,即只复制节点本身,不复制里面的子节点。
如果括号参数为true,则是深拷贝,即会复制节点本身及里面所有的子节点。
示例:点击按钮,克隆一个列表
<ul class="list1"> <li>橘子</li> <li>苹果</li> </ul> <button onclick="fun()">点击按钮,克隆该列表</button> <ul class="list2"></ul> <script> function fun() { //获取list1元素 var ul1 = document.querySelector(".list1"); //获取list2元素 var ul2 = document.querySelector(".list2"); //克隆list1节点 var cloneItem = ul1.cloneNode(true); //把克隆后的内容添加到list2元素内 ul2.appendChild(cloneItem); } </script>
点击前:
点击后: