网页中所有内容都是节点(标签、属性、文本、注释、空格、换行等,即万物可节点)在dom中,节点用哪个node来表示,所有节点都可通过js进行访问,所有html元素(节点)均可被增删改。
通过节点操作获取元素,它与dom提供的方法获取元素的区别:
- 节点操作获取是利用父子兄弟节点关系获取元素
- 逻辑性强且简单,但是兼容性稍差
节点概述
节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
节点类型
- 元素代表1
- 属性代表2
- 文本代表3
节点层级
父级节点
得到的是离元素最近的父级节点(亲爸爸)
孩子.parentNode;
子节点
childNodes(不提倡)
父亲.childNodes; //注意:返回的是所有节点,包含元素节点,文本节点,比如空格与换行等。
如果只想要获取里面的元素节点,还需要专门的处理,所以一般不提倡使用childNodes
<script> var ul=document.querySelector('ul'); for(var i=0;i<ul.childNodes.length;i++){ if(ul.childNodes[i].nodeType == 1){ //判断ul.childNodes[i]是元素节点 console.log(ul.childNodes[i]); } } </script>
children(非标准)(重点且推荐)
获取所有子元素的节点
父亲.children;
获取第一个子元素节点
var ul=document.querySelector('ul'); console.log(ul.children[0]);获取第一个子元素节点
测试:
<script> // 1. 获取元素 var nav = document.querySelector('.nav'); var lis = nav.children; // 得到4个小li // 2.循环注册事件 for (var i = 0; i < lis.length; i++) { lis[i].onmouseover = function() { this.children[1].style.display = 'block'; } lis[i].onmouseout = function() { this.children[1].style.display = 'none'; } } </script>结果演示
兄弟元素节点(有兼容性问题)
返回当前元素的下一个兄弟元素节点
兄弟.nextElementSibling
返回当前元素的上一个兄弟元素节点
兄弟.previousElementSibling
举例:
<div>1</div> <span>2</span> <script> var d=document.querySelector('div'); console.log(d.nextElementSibling); </script>
封装一个函数解决兼容性问题
function getNextElementSibling(element){ var el=element; while(el=el.nextSibling){ if(el.nodeType==1){ return el; } } return null; }
动态创建节点
创建节点
document.createElement('节点'); //动态创建元素节点
添加节点
将一个节点添加到父节点的子节点列表末尾。
父亲.appendChild(节点)
<ul></ul> <script> //创建一个元素节点 var l=document.createElement('li'); //添加创建好的节点 var u=document.querySelector('ul'); u.appendChild(l); </script>
在指定元素节点前面添加节点
父亲.insertBefore(节点,指定元素的前面/ul.children[0])
删除节点
父亲.remonveChild(节点)
简单留言小测试
<script> var v=document.querySelector('input'); var b=document.querySelectorAll('button'); var u=document.querySelector('ul'); //发布留言 b[0].onclick=function(){ var data=v.value; //创建元素 var l=document.createElement('li'); l.innerHTML=data+'<a href="javascript:;">删除</a>'; //添加元素 // u.appendChild(l); u.insertBefore(l,u.children[0]); //删除指定留言 var a=document.querySelector('a'); //给每个留言添加事件 a.onclick=function(){ //a的父节点就是l u.removeChild(a.parentNode); } } //依次删除留言 // b[1].onclick=function(){ // var l=document.querySelector('li'); // u.removeChild(l); // } </script>结果演示
复制节点
父节点.cloneNode();括号为空或着里面是false 则代表浅拷贝,只复制标签不复制里面的内容 父节点.cloneNode(true);深拷贝 则复制标签和内容
<ul> <li>1</li> <li>2</li> </ul> <script> var u=document.querySelector('ul'); var ll=u.children[0].cloneNode(true); u.appendChild(ll); </script>
三种动态创建元素的区别
- document.write()
- element.innerHTML
- document.createElement()
区别:
- document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘(新页面)
- innerHTML创建多个元素时采取数组形式拼接,效率更高,但结构稍微复杂。而采取字符串拼接时效率最低。
- createEl.ement()创建多个元素效率稍微低一点点,但是结构更清晰。
<script> function fn() { // var d1 = +new Date(); var array = []; for (var i = 0; i < 1000; i++) { array.push('<div></div>'); } document.body.innerHTML = array.join(''); // var d2 = +new Date(); console.log(d2 - d1); } fn(); </script>
案例
<script> var datas=[ { name:"渣渣龙",kemu:"js",cj:"98" }, { name:"王学龙",kemu:"js",cj:"98" }, { name:"王小明",kemu:"js",cj:"98" } ]; var kuang=document.querySelector('tbody'); for(i=0;i<datas.length;i++){//管理行 tr //创建行 var tr=document.createElement('tr'); kuang.appendChild(tr); //创建3个单元格 for(j in datas[i]){ //管理列/单元格td var td=document.createElement('td'); td.innerHTML=datas[i][j];//对象里第一个数组里的第一个属性名的属性值 //往单元格里给值 tr.appendChild(td); } //创建每一行的最后一个单元格放 删除 var td=document.createElement('td'); td.innerHTML='<a href="javascript:;">删除</a>'; tr.appendChild(td); td.onclick=function(){ // 删除当前a所在的行,即a的爸爸的爸爸 :a所在的单元格 单元格所在的行 kuang.removeChild(this.parentNode); } } // for(var k in obj) { // k 得到的是属性名 // obj[k] 得到是属性值 // } </script>结果演示