节点操作
[ 导语 ] DOM 提供节点操作的方法,是因为:DOM 节点关系指针都是只读的。
123456789101112 通过修改myUl的父级节点来修改其节点关系,但由于parentNode属性是只读的,所以修改无效,在IE8-浏览器下甚至会报错。<div id="myDiv"></div><ul id="myUl"><li id="myli"></li></ul><script>console.log(myUl.parentNode); // <body>myUl.parentNode = myDiv;// 标准浏览器下,依然返回<body>;而IE8-浏览器则会报错console.log(myUl.parentNode);</script>
获取页面元素
为什么要获取页面元素?
例如,我们想要操作页面上的某部分(显示/隐藏),需要先获取到该部分对应的元素,才能进行后续操作。
DOM获取节点通常有以下两种方式:
1. 通过节点关系获取节点 // 缺点:可维护性差(一旦节点位置发生变化,就会影响到通过关系获取节点)
2. 通过接口获取节点,主要有以下几个方法:
[1] element = document.getElementById(id)?↓ 根据 id 获取元素
element 是一个 Element 对象,如果当前文档中拥有特定 ID 的元素;不存在,则返回null。
1 2 3 |
// only document / sole var hello = document.getElementById("hello"); |
[2] collection = element.getElementsByTagName(tagName)?↓ 根据标签名获取元素
该方法接收一个参数,即要取得元素的标签名,返回包含0或多个元素的类数组对象HTMLCollection。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// collection is live <div id="users"> <h2>8882人在学习该课程:</h2> <ul> [ <li class="user">Satoshi</li> li.user <li class="user">春来草青</li> li.user <li class="user last">Kash</li> li.user.last </ul> ] </div> users.getElementsByTagName("li") users.getElementsByTagName("li")[2] // li.user.last users.getElementsByTagName("*") // 获取所有后代元素 |
[3]collection =element.getElementsByClassName(className)?↓
1 2 3 4 5 |
users.getElementsByClassName("user") users.getElementsByClassName("user")[2] // li.user.last users.getElementsByClassName("user last") // li.user.last // 兼容性问题:IE8-浏览器不支持 |
[4] list = element.querySelector/All(selector)?↓ 根据选择器来获取元素
1 2 3 4 5 6 7 |
// list不是动态的,一旦获取就不会变化 var users = document.querySelector("#users"); // div#users users = querySelectorAll(".user"); // [li.user,li.user,li.user.last] document.querySelectorAll("#users .user"); // 同上 // 兼容性问题:所有移动端浏览器都支持;PC端,IE8+支持 |
元素的内容?↓
[1] innerHTML & innerText:用于获取开始标签和结束标签之间的内容。区别在于:
- innerHTML:获取内容的时候,如果内容内容中有标签,也会把标签获取到(原封不动把内容获取到);
- innerText:获取内容的时候,如果内容中有标签,会把标签过滤掉(会把前后的换行和空白都去掉);
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<div id="box"> 我是一个div <span>这是一个span</span> </div> <script> var box = document.getElementById('box'); console.log(box.innerHTML); /* 我是一个div <span>这是一个span</span> */ console.log(box.innerText); // 我是一个div 这是一个span </script> // innerHTML是万能的,但存在覆盖之前的事件状态、内存泄漏、安全等问题,建议仅用于创建新的节点。 |
[ 设置标签之间的内容 ]
1234567 box.innerHTML = ''; // 清空内容// 通过 innerHTML 设置内容,如果内容中有标签,会以HTML的方式进行解析box.innerHTML = '<b>测试</b>内容';// 通过 innerText 设置内容,如果内容中有标签,会把标签在网页上显示出来(纯文本 - 转义字符原理)box.innerText = '<b>测试</b>内容';
[2] innerText & textContent:用于获取内部文本,其主要区别在于浏览器的兼容问题。
- 谷歌:两个都支持
- 新版的FF:两个都支持
- 旧版的FF:只支持 textContent
- 新版的IE(IE9+):两个都支持
- 旧版的IE:只支持 innerText
1 2 3 4 5 6 7 8 9 10 11 12 |
var box = document.getElementById('box'); console.log(getInnerText(box)); // 处理innerText的兼容性问题 function getInnerText(element){ // 判断当前浏览器是否支持元素的innerText属性。支持,则使用element.innerText获取内容,不支持,则使用element.textContent获取内容 if(typeof element.innerText === 'string'){ return element.innerText; }else{ return element.textContent; } } |
动态创建元素
[1] 创建节点?! element = document.creatElement(tagName)
1 2 |
// 创建指定标签名称的元素 var li = document.creatElement("li"); |
[2] 插入节点?!
- 在指定元素后面追加子节点 var achild = element.appendChild(achild);
12345678910 <div id="users"><h2>8882人在学习该课程:</h2><ul></ul></div>var h2 = document.creatElement('h2');h2.innerTest = "8882人在学习该课程:";var ul = document.creatElement('ul');users.appendChild(h2);users.addpendChild(ul);
- 在指定元素的指定子节点前面添加节点 var achild = element.insertBefore(achild,referenceChild);
12345678910 <div id="users"><h2>8882人在学习该课程:</h2><ul></ul></div>var h2 = doucment.creatElement("h2");h2.innerText = "8882人在学习该课程:";var ul = document.creatElement('ul');users.appendChild(ul);users.insertBefore(h2,ul);
[3] 删除节点?! child = element.removeChild(child)
1 2 |
var user2 = users.getElementsByClassName("users")[1]; user2.parentNode.removeChild(user2); |
[4] 其他常用元素操作的方法
- 替换节点 oldChild.parentNode.replaceChild(newChild, oldChild);
123456789101112131415 <div id="div1">1</div><div id="div2">2</div><div id="div3">3</div><button id="btn1">新增节点替换(4替换2)</button><button id="btn2">原有节点替换(3替换1)</button><script>btn2.onclick = function(){document.body.replaceChild(div3,div1);}btn1.onclick = function(){var div4 = document.createElement('div');div4.innerHTML = '4';document.body.replaceChild(div4,div2);}</script>
- 复制节点 list = element.cloneNode( true | false ) boolean值,表示是否执行深复制
cloneNode()不会复制添加到DOM节点中的JS属性,如事件处理等;只复制特性和子节点,其他一切都不会复制。
123456789101112131415161718 <ul id="list"><li>1</li><li>2</li><li>3</li></ul><script>var oList = document.getElementById('list');oList.index = 0;var deepList = oList.cloneNode(true);// 成功复制子节点console.log(deepList.children.length);// 3// 但并没有复制属性console.log(deepList.index);//undefinedvar shallowList = oList.cloneNode();// 浅复制不复制子节点(复制节点本身)console.log(shallowList.children.length);// 0</script>