一、DOM操作
1-NodeList:
a-NodeList是一个节点的集合(既可以包含元素和其他节点),在DOM中,节点的类型总共有12种,通过判断节点的nodeType来判断节点的类型。
b-NodeList对象有个length属性和item()方法,length表示所获得的NodeList对象的节点个数,这里还是要强调的是节点,而item()可以传入一个索引来访问Nodelist中相应索引的元素。
c- js 节点有11种类型,但是与html相关的只有6个
类型名称 | 常数值 |
---|---|
元素节点 | 1 |
属性节点 | 2 |
文本节点 | 3 |
实体名称节点 | 6 |
文档节点 | 9 |
文档片段节点 | 11 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>遍历元素节点</title> </head> <body> <ul> <li>item1</li> <li>item2</li> <li>item3</li> <li>item4</li> <li>item5</li> </ul> </body> <script> var cl = console.log.bind(console); var ul = document.querySelector("ul"); cl(ul); // 子节点 cl(ul.childNodes); cl(ul.childNodes.length); cl(ul.childNodes[2]); // js节点 cl(ul.childNodes[0]); cl(ul.childNodes[0].nodeType); cl(ul.childNodes[1].nodeValue); cl(ul.childNodes[1].nodeName); // 最后一个 cl(ul.childNodes[ul.childNodes.length - 1]); cl(ul.childNodes[ul.childNodes.length - 2].nodeName); // 遍历 var eles = []; ul.childNodes.forEach(function (item) { // 只返回类型为1的元素节点 if (item.nodeType === 1) this.push(item); }, eles); cl(eles); //获取第一个子节点 cl(ul.firstChild); // cl(ul.childNodes[0]); cl(ul.childNodes[ul.childNodes.length - 1]); // 最后一个子节点 cl(ul.lastChild); // 前一个兄弟节点 cl(ul.lastChild.previousSibling); // 后一个兄弟节点 cl(ul.firstChild.nextSibling); </script> </html>
2-HTMLCollection
a-HTMLCollection是元素集合,它和NodeList很像,有length属性来表示HTMLCollection对象的长度,也可以通过elements.item()传入元素索引来访问。
b-HTMLCollection的集合和NodeList对象一样也是动态的,他们获取的都是节点或元素集合的一个引用。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>遍历元素节点</title> </head> <body> <ul> <li>item1</li> <li>item2</li> <li>item3</li> <li>item4</li> <li>item5</li> </ul> </body> <script> var cl = console.log.bind(console); var ul = document.querySelector("ul"); // children // childNodes: 返回所有节点,包括元素,文本... cl(ul.childNodes); // children: 只返回元素 cl(ul.children); cl(ul.children.length); cl(ul.childElementCount); // 第一个元素 cl(ul.firstElementChild); // 最后一个 cl(ul.lastElementChild); // 任何一个 cl(ul.children[2]); // 前一个兄弟 cl(ul.children[2].previousElementSibling); //后一个兄弟 cl(ul.children[3].nextElementSibling); // HTMLCollection没有forEach cl("-----------"); for (var i = 0; i < ul.childElementCount; i++) { cl(ul.children.item(i)); } </script> </html>
3-NodeList和HTMLCollection的区别:
NodeList:文档节点集合
HTMLCollection: 文档元素集合
HTMLCollection相当于是NodeList中type=1的节点集合
二、事件
1-事件添加方式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>事件添加方式</title> </head> <body> <button onclick="var text=this.innerText;alert(text);">按钮1</button> <button onclick="show(this)">按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> </body> <script> var cl = console.log.bind(console); //1. 给html元素绑定事件属性 function show(ele) { var text = ele.innerText; alert(text); } // 2. 给html元素添加属性 var btn3 = document.querySelector("button:nth-of-type(3)"); btn3.onclick = function () { alert(this.nodeName); }; // 3. 监听器 var btn4 = document.querySelector("button:nth-of-type(4)"); // btn4.addEventListener(事件类型, 事件回调函数, 传递机制) btn4.addEventListener( "click", function () { alert(this.innerText); }, // false: 冒泡阶段触发 false ); // 4. 事件派发 var btn5 = document.querySelector("button:last-of-type"); btn5.addEventListener( "click", function () { alert(this.innerText); }, false ); // 创建一个事件对象 var ev = new Event("click"); // 不用点击,也会自动的触发点击事件 btn5.dispatchEvent(ev); </script> </html
2-事件委托/代理
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>事件传递与事件委托/代理</title> </head> <body> <div class="first"> <div class="second"> <div class="three">事件传递</div> </div> </div> </body> <script> // 事件的捕获与冒泡 var cl = console.log.bind(console); var first = document.querySelector(".first"); var second = document.querySelector(".second"); var three = document.querySelector(".three"); // true: 捕获阶段触发事件 first.addEventListener( "click", function (ev) { // ev: 事件对象 // ev.type: 事件类型 // ev.target: 触发事件的元素 // ev.currentTarget: 绑定事件的元素 // cl(ev.target.classList.item(0)); cl( "捕获阶段:" + "触发: " + ev.target.classList.item(0), "绑定:" + ev.currentTarget.classList.item(0) ); }, true ); second.addEventListener( "click", function (ev) { cl( "捕获阶段:" + "触发: " + ev.target.classList.item(0), "绑定:" + ev.currentTarget.classList.item(0) ); }, true ); three.addEventListener( "click", function (ev) { cl( "捕获阶段:" + "触发: " + ev.target.classList.item(0), "绑定:" + ev.currentTarget.classList.item(0) ); }, true ); // false: 冒泡阶段触发事件 first.addEventListener( "click", function (ev) { // ev: 事件对象 // ev.type: 事件类型 // ev.target: 触发事件的元素 // ev.currentTarget: 绑定事件的元素 // cl(ev.target.classList.item(0)); cl( "冒泡阶段:" + "触发: " + ev.target.classList.item(0), "绑定:" + ev.currentTarget.classList.item(0) ); }, false ); second.addEventListener( "click", function (ev) { cl( "冒泡阶段:" + "触发: " + ev.target.classList.item(0), "绑定:" + ev.currentTarget.classList.item(0) ); }, false ); three.addEventListener( "click", function (ev) { cl( "冒泡阶段:" + "触发: " + ev.target.classList.item(0), "绑定:" + ev.currentTarget.classList.item(0) ); }, false ); </script> <!-- 冒泡实现事件的委托/代理 --> <ul> <li>item1</li> <li>item2</li> <li>item3</li> <li>item4</li> <li>item5</li> </ul> <script> document.querySelectorAll("ul li").forEach(function (item) { item.addEventListener("click", function (ev) { cl(this === ev.target); cl("当前触发事件的元素是:", this); }); }); // 事件委托/代理: 子元素上的事件会冒泡到父元素上的同名事件上触发 // document.querySelector("ul").addEventListener("click", function (ev) { // // cl(ev.target); // // cl(ev.currentTarget); // // cl(this === ev.currentTarget); // cl("当前触发事件的元素是:", ev.target); // }); </script> </html>
三、事件捕获与冒泡的原理
事件捕获: 就是像捕鱼收网那样,从外向里面触发。
冒泡: 像水烧开了一样,从内向外面扩散触发。
四、总结:通过本节课的学习对捕获与冒泡的原理有了认识,知道了事件委托/代理的实现方式,DOM中的NodeList与HTMLCollectio区别。