节点操作:
- 添加节点
- 删除节点
- 修改节点
- 查找节点
创建节点
<script>
document.write("<p>js内容</p>");
</script>
<p>html内容</p>
<script>
document.write("<p>js内容2</p>");
</script>
create 系列创建节点的方法
document.createElement();
document.createTextNode(); //文本节点
document.createDocumentFragment(); //文档片段
document.createComment(); //注释文本,注释节点
//括号里包裹的标签不区分大小写。
<body>
<ul id="myid"></ul>
</body>
//html加载完成之后运行,否则获取不到ul
window.onload=function (){
var ul = document.getElementById('myid');
var li = document.createElement('li');
var txt = document.createTextNode('内容');
ul.appendChild(li);
li.appendChild(txt);
}
注释节点很少动态创建:
在ul节点前插入一段注释:
document.createElement 还能支持创建当前浏览器不支持的标签名,在IE6-8下,这是一个著名的hack。
高效创建节点
innerHTML(); //用来设置或获取当前标签的起始和结束里面的内容(无标签)
outerHTML(); //返回调用它的元素及所有子节点的HTML标签
innerText(); //
outerText(); //
innerHTML()
这里注意,原本的内容并不会显示,相当于覆盖掉了。
<div id="didi">原始</div>
window.onload=function (){ //html加载完成之后运行
var diva=document.getElementById("didi");
var str="内容"
+"<ul>"
+"<li>1</li>"
+"<li>2</li>"
+"<li>3</li>"
+"</ul>";
diva.innerHTML =str;
}
也可以读取节点:
alert(diva.innerHTML);
限制:
- 字符串的最左边不能出现空白,IE6-8会自动移除掉他
- 大多数浏览器不会对script标签进行脚本执行操作
- 不能单独创建meta,style,link等元素,一定要在前面加上一些字符
不成功:
成功:
outerHTML
返回调用它的元素及所有子节点的HTML标签:
覆盖掉原本所有的内容:
节点遍历
documentElement 属性可返回文档的根节点
tagName 属性返回元素的标签名
ownerDocument直接获取根节点
hasChildNodes()判断其是否存在子节点
以上方法,遍历节点时,在存在空白节点:
去除空白节点过滤:
还有一种方法,使用第二组api:
childElementCount获取所有子节点的个数,不包含后代元素。
类数组对象:
NodeList
特点:
- NodeList 是一种类数组对象,用于保存一组有序的节点
- 可以通过方括号语法来访问NodeList的值,有item方法与length属性
- 它并不是Array的实例,没有数组对象的方法
在这里,是不能使用push方法添加节点的。
怎么才能使用push方法对其添加节点呢,将其转换为数组就可以了:
这个时候,我们就可以使用push增加节点了:
然而这里并不会在页面中显示出来,因为只是装填进数组中,怎么显示,后边会讲。
也有简单高效方法,但是再IE低版本无法运行:
可以兼容使用:
HTMLCollection
html元素的集合
- Ele.getElementsByTagName() 根据节点的名称,返回一组元素的集合
- document.scripts
- document.links
- document.images
- document.forms
- tr.cells
- select.options
- …
全部以类数组对象方式呈现:
这个方法,如果这个集合里有id为td的元素,就返回这个,如果没有就寻找name有td的,返回,(如果有两个,那么只返回第一个)。
NamedNodeMap
访问元素节点的Ele.attributes
类数组对象的动态性:
- NodeList,HTMLCollection,NamedNodeMap三个集合都是动态的,是有生命、有呼吸的对象
- 它们实际上是基于DOM结构动态执行查询的结果,因此DOM结构的变化能够自动反映这些对象中
- 每当文档结构发生变化时,它们都会得到更新。因此,它们始终都会保存着最新、最准确的信息
举个例子:
这个例子中有三个div,我们给每个div中添加三个div,但是这么写的话,就会陷入死循环,因为他具有随时更新的动态性,会进行无限添加无限寻找。
如何不死循环:
节点查找:
1. getElementByld()
2. getElementsByName()
3. getElementsByTagName()
4. getElementsByClassName()
5. querySelector()
6. querySelectorAll()
1、2使用时前面要加document,必须使用document
注意2、3、4是Elements
1、2、3 基本支持所有的浏览器,IE6~IE8也可以使用,4、5、6只能在较新的浏览器上支持
//举例:获取其下第一个(0)
var ul = getElementById('ull');
ul.children.item(0);
getElementByld()
可以通过某个元素的id属性找到这个元素。
<div id="d1">id获取</div>
var name = document.getElementById('d1');
console.log(name.tagName);//获取其标签。注意要文档解析完成之后才可以执行,否则获取不到。
在使用时,出现多个相同id时,会获取到第一个。
bug : 在IE7及以前的浏览器获取,name="num" id="num"
,会获取到前面的name="num"
,
利用ie浏览器与其他浏览器的解析差别,修复bug:
getElementsByName()
通过元素的name属性获取元素。
这里Elements是加了s的,说明返回的结果是个集合,因为name属性不唯一。
<div name="d1">ia1</div>
<div name="d1">阿松大</div>
<div name="d1">阿大</div>
<button onclick="a1();">执行js</button>
function a1(){
var name = document.getElementsByName('d1');
console.log(name.length);//4
console.log(name[1]);//返回整个标签
console.log(name);//返回一个类数组
}
getElementsByTagName()
根据标签元素的名称获取元素,同样是获得一组元素。
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
window.onload = function (){//文档完全加载完成后执行
var name = document.getElementsByTagName('li');
console.log(name.length);
console.log(name[0]);
console.log(name[0].textContent); //input使用.value
console.log(name);
}
在参数中传入一个*
,获取所有的代码节点,再加上一个for循环就可以遍历出来全部的节点。
window.onload = function (){
var all = document.getElementsByTagName('*');
for (i=0,len = all.length;i<len;i++){
console.log(all[i].tagName);
}
}
getElementsByClassName
可以传入一个或多个类名,多个类名用空格隔开。
<ul id="ulbox">
<li class="lii">1</li>
<li class="lii li2">2</li>
<li class="lii">3</li>
</ul>
window.onload = function (){
var ulbox = document.getElementById("ulbox");
var libox = ulbox.getElementsByClassName("lii");
var li2 = ulbox.getElementsByClassName("lii li2");
console.log(libox);
console.log(li2);
}
getElementsByClassName
在较新的浏览器中才支持,如果需要在旧浏览器中支持需要自己实现其功能。注意:
- 类名可以在文档的任何位置进行查找
- 根据标签名过滤一些元素
- 做到兼容
- 支持该属性的直接使用
可提前封装好一个js文件,使用的时候直接引入,具体代码百度。
querySelector () 和 querySelectorAll ()
根据css选择器的规范,便捷的定位文档中的指定元素。
几乎所有浏览器都支持,IE中支持到IE8。
querySelector
返回一个元素
querySelectorAll
返回一组元素
//-------querySelector-------
<ul id="ulbox">
<p id="duanluo">p元素</p>
<li class="lio">1</li>
<li class="lio lio1:bar">2</li>
<li class="lio lio1 ">3</li>
</ul>
window.onload = function(){
var ulbox = document.getElementById("ulbox");
var lio = ulbox.querySelector("#duanluo");
var li1 = ulbox.querySelector("li:last-child");
var li2 = document.querySelector('ul p'); //文档中ul下的p元素,注意这里是document
var li3 = document.querySelector('ul,li');//文档下的ul和li,但是没有加All,所以只会返回ul
var li33 = document.querySelectorAll('ul,li'); //返回ul和li
var nul = document.querySelector('span'); //找不到所获取的元素,返回null
var li4 = document.querySelector('.lio1'); //使用类名
var li5 = document.querySelector('.lio1\\:bar');
//有违规字符时需要转义符 \,因为\同样是违规字符,所以在\前再加一个\
console.log(lio); //<p id="duanluo">p元素</p>
console.log(lio.innerHTML); //p元素
console.log(li1); //<li class="lio">3</li>
console.log(li2); // <p id="duanluo">p元素</p>
console.log(li3);
console.log(li33);
console.log(li4);
console.log(li5);
}
//-------querySelectorAll-------
// 返回的是nodeList,是类数组对象,具有动态性,可以陷入死循环
<div id="ulbox">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
window.onload = function () {
var ulbox = document.getElementById("ulbox");
var li1 = ulbox.querySelectorAll("ul");
var li2 = ulbox.querySelectorAll("li");
var li3 = ulbox.querySelectorAll("span");
console.log(li1);
console.log(li2);
console.log(li3);
}
操作节点:
1. appendChild
2. insertBefore
3. replaceChild
4. cloneNode
5. normalize
6. splitText
appendChild ()
为指定元素节点的最后一个子节点添加节点。
该方法返回新的子节点。
<ul id="ull">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var ull = document.getElementById('ull');
var txt = document.createTextNode('4'); //创建内容
var li = document.createElement('li'); //创建元素
var firstli = ull.firstElementChild; //2获取到第一个元素,li1
li.appendChild(txt); //内容填进元素
ull.appendChild(li); //新增整体添加到ul里
ull.appendChild(firstli); //填充到最后,这样使用相当于放到最后
insertBefore ()
在指定的已有的子节点之前插入新的子节点。
insertBefore ( newnode , existingnode )
newnode 必须。需要插入的节点对象
existingnode 可选。未规定或写null则会在结尾插入,实现与appendChild一样的效果
<ul id="ull">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var ull = document.getElementById('ull');
var txt = document.createTextNode("4");
var linew = document.createElement("li");
linew.appendChild(txt);
var li2 = ull.children.item(1);//获取到第二个元素
ull.insertBefore(linew,li2); //在第二个节点前插入
ull.insertBefore(linew,null); //在最后插入
ull.insertBefore(linew); //在最后插入
ull.insertBefore(linew,ull.firstElementChild);
//插入第一个,这种写法也支持
ull.insertBefore(linew,ull.lastElementChild);
//插入最后一个,这种写法也支持
replaceChild
该方法用新节点替换某个子节点。
返回被替换的节点,注意是被替换掉的节点。
replaceChild ( 要插入的节点 , 被替换的节点 ) ;
<ul id="ull">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var ull = document.getElementById('ull');
var txt = document.createTextNode("4");
var linew = document.createElement("li");
linew.appendChild(txt);
var li2 = ull.children.item(1);//获取到第二个元素
var tihuan = ull.replaceChild(linew,li2); //替换第二个
console.log(tihuan); //返回被替换掉的
cloneNode
创建节点的拷贝,并返回该副本。
cloneNode ( )
默认为false,不复制子节点。为true时进行深度复制,复制子节点
拷贝的节点要有父节点,如果没有父节点,要通过appendChild ()、insertBefore ()、replaceChild ()
等方法进行添加
<ul id="ull">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var ull = document.getElementById('ull');
var ele1 = ull.cloneNode(false);
var ele2 = ull.cloneNode(true);
console.log(ele1);
console.log(ele2);
document.body.appendChild(ele2); //添加进文档里
normalize
合并相邻的Text节点。
var ele = document.createElement('div');
var txt1 = document.createTextNode('第一节文本');
ele.appendChild(txt1);
var txt2 = document.createTextNode('第二节文本');
ele.appendChild(txt2);
document.body.appendChild(ele);
console.log(ele.childNodes.length);
ele.normalize();
console.log(ele.childNodes.length);
如何获取合并以后的文本内容呢:
console.log(ele.firstChild.nodeValue);
splitText ()
按照指定的位置把文本节点分割为两个节点。
原来的文本节点包含从开始到指定位置之前的内容,新文本节点包含剩下的内容。
返回新的文本节点。
var ele = document.createElement('div');
var txt1 = document.createTextNode('这是一个很长的文本节点');
ele.appendChild(txt1);
document.body.appendChild(ele);
var newele = ele.firstChild.splitText(5);
//ele.firstChild获取到的是其文本节点,
//splitText(5) 从第五个开始截取,01234 | 5678...
console.log(ele.firstChild.nodeValue); //原来div子节点的值
console.log(newele.nodeValue); //新的div子节点的值
console.log(ele.childNodes.length );
删除节点:
1. removeChild ()
2. removeNode ()
3. innerHtml ()
4. deleteContents ()
5. textContent ()
removeChild ()
方法指定元素的某个指定的子节点。
以 Node 对象返回被删除的节点,如果节点不存在则返回 null。
<ul id="ulbox">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var ul = document.getElementById('ulbox');
console.log(ul.childNodes.length);
//注意这里的用法,父.removeChild(子)
var shanchude = ul.removeChild(ul.firstElementChild);
console.log(shanchude);
console.log(ul.childNodes.length);
removeNode ()
IE的私有实现。
将目标节点从文档中删除,返回目标节点。
参数是布尔值,默认是false,如果传入true,那么和removeChild ()
类似
<ul id="ulbox">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var ul = document.getElementById('ulbox');
var shanchude = ul.removeNode(); //只删除ul
var shanchude = ul.removeNode(true); //删除ul及其后代元素
console(shanchude.outerHTML);
removeChild () 与 innerHTML的区别
removeChild
清除之后,依然在内存中,不被释放
innerHTML = ""
清空之后,不在占用内存
使用效果在普通浏览器上是一样的,还能够获取到还能使用。
IE6-8中:
removeChild
是删除了,但是还能获取到,还能使用
innerHTML = ""
无法获取到