也有一个文本节点,其 nodeValue 的值为 "Hello World!" 。
##### parentNode、firstNode、lastNode、nextSibling、previousSibling
DOM结构如下
hello word1
hello word2
hello word3
hello word4

总结:
- 1、父节点的 firstChild 和 lastChild属性分别指向其 childNodes 列表中的第一个和最后一个节点。firstChild等于childNodes[0],lastChild原理一样;
- 2、在只有一个子节点的情况下, firstChild 和lastChild 指向同一个节点。如果没有子节点,那么 firstChild 和 lastChild 的值均为 null 。
- 3、如果列表中只有一个节点,那么该节点的 nextSibling 和 previousSibling 都为 null
### Node的方法
- appendChild
- insertBefore
- replaceChild
- cloneNode
- hasChildNodes
##### appendChild
将节点添加到指定容器的最后面,返回新增的节点。
hello word1
hello word2
hello word3
hello word4
参考:[https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild)
##### insertBefore
将新的节点添加到指定容器中某一个节点的前面,方法接受两个参数:要插入的节点和作为参照的节点。
var insertedNode = parentNode.insertBefore(newNode, referenceNode);
插入节点后,被插入的节点会变成参照节点的前一个同胞节点( previousSibling ),同时被方法返回。
如果参照节点是null ,则 insertBefore() 与 appendChild() 执行相同的操作
https://developer.mozilla.org/en-US/docs/Web/API/Node/insertbefore
##### replaceChild
把原有的元素进行替换
replacedNode = parentNode.replaceChild(newChild, oldChild);
- 如果newChild已经存在于DOM树中,首先会被删除;
- oldChild会被newChild所取代,olcChild是被替换掉的原始节点
- replacedNode
##### cloneNode
赋值节点
var dupNode = node.cloneNode(blooeanValue);
- node是被赋值的节点
- dupNode是赋值后的文件;
- blooeanValue 是否采用深度克隆
- 如果为true,则该节点的所有后代节点也都会被克隆
- 如果为false,则只克隆该节点本身.
- 虽然 blooeanValue是可选的参数,但是推荐当做必须参数用;
备注:
- 克隆一个元素节点会拷贝它所有的属性以及属性值,当然也就包括了属性上绑定的事件(比如onclick="alert(1)"),但不会拷贝那些使addEventListener()方法或者node.onclick = fn这种用JavaScript动态绑定的事件.
- 推荐:平时写代码的时候,用事件委托的方式去写代码;
- **clonenode()可能导致文件重复的元素ID**,如果原始节点设置了ID,并且克隆节点会被插入到相同的文档中,那么应该更新克隆节点的ID以保证唯一性。name属性可能也需要进行修改
- 想要克隆一个节点来添加到另外一个文档中,请使用Document.importNode()代替本方法.
##### removeChild
该方法从指定的DOM结构中,删除一个子元素;返回值是要删除的节点;
hello word1
hello word2
hello word3
hello word4
- oTest1和parent1是父子节点的关系;
- returnValue===oTest1,
- 如果要删除的和被删除的节点不是父子关系,会报错
- 子元素不存在:parameter 1 is not of type 'Node'.
- 要删除的子元素,不是父元素内的子元素:The node to be removed is not a child of this node.
参考:[https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild](https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild)
##### hasChildNodes
返回一个布尔值,表明当前节点是否包含有子节点.
> 语法:element.hasChildNodes()
> 注意:Node.hasChildNodes是个方法,而不是普通属性,使用时必须加括号才能调用.
var foo = document.getElementById("foo");
if ( foo.hasChildNodes() ) {
foo.removeChild( foo.childNodes[0] );
}
如果id为foo的这个元素有子节点,则从dom树中删除它的第一个子节点.
# Document类型
- 查找元素
- 特殊集合
- 文档写入
- 文档的子节点
- 文档信息
- DOM一致性检测
输出document,查看有哪些属性和方法;
console.dir(document);
### 查找元素
查看 Document 上的方法,最常用的就是查找元素的方法了;document的意思是整个页面的
console.log(document)
输出看一下;
- getElementById
- getElementsByClassName
- getElementsByName
- getElementsByTagName
- querySelector
- querySelectorAll
###### document.getElementById()
**在整个文档中,通过元素的ID获取这个元素的对象,如果页面中没有这个ID,则获取的内容为null;**
需要注意的
> getElementById这个方法的写法,不能改变大小写;
> document.getElementById("id"); 前面的范围,必须是document;
> id是大小写敏感的字符串,代表了所要查找的元素的唯一ID.element是一个元素的,一个,找到的也是第一次找到id的所在元素;
> getElementById方法不会搜索不在文档中的元素。当创建一个元素,并且分配ID后,你必须要使用insertBefore或其他类似的方法把元素插入到文档中之后才能使用 getElementById 获取到:如果不插入文档中,属于游离状态,此时获取是获取不到的;
var element = document.createElement("div");
element.id = 'testId';
console.log(document.getElementById('testId'));//null
document.body.appendChild(element);
console.log(document.getElementById('testId'));//
hello word1
hello word2
hello word3
hello word4
###### document.getElementsByClassName()
**在整个文档中,通过元素class样式类的值来获取一组元素,IE678不兼容**
var elements = document.getElementsByClassName(names);
// or:
var elements = rootElement.getElementsByClassName(names);
- elements 是复数,多个class的意思,查找到的所有元素的集合 HTMLCollection .返回的是一个类数组,如果找到某一个class,可以借助前面的范围,并且[0],这样的方式来确定某一个元素;
- names 是一个字符串,表示用于匹配的 class 名称列表; 多个 class 名称通过空格分隔
- getElementsByClassName 可以在任意的元素上调用,不仅仅是 document。 调用这个方法的元素将作为本次查找的根元素(范围);
###### document.getElementsByTagName()
**在整个文档中,通过元素的标签名来获取一组元素(HTMLcollection集合),获取的是一个类数组,获取的个数可以通过length获取,获取集合的某一个元素,通过对象的索引即可查找;**
即使一个文档里面,只有一个元素集合;这个元素也需要用[0]的方式给选出来,否则操作的是一个类数组;
###### document.getElementsByName()
**在整个文档中,通过元素的name值来获取一组元素(NodeList集合),在IE浏览器中,此方法只对表单元素起作用;**
hello word1
hello word2
hello word3
hello word4
###### document.querySelector() 在整个文档中,通过不同的选择器获取一个元素对象,IE678不兼容
###### document.querySelectorAll() 在整个文档中,通过不同的选择器获取一组元素对象集合,IE678不兼容;
###### document.documentElement 获取整个HTML对象
###### document.body 获取整个body对象
### 特殊集合
除了属性和方法,document对象还有一个特殊的集合,这些集合都是HTMLCollection对象,为了访问文档常用的部分提供的快捷方式;
正常工作中,很少直接这么用的;
- document.anchors 包含文档中所有带name特性的
元素;
- document.links 包含文档中所有带href特性的元素,
- document.forms 包含文档中所有带form的元素,与document.getElementsByName("form")相同;
- document.imges 包含文档中所有带
的元素,与document.getElementsByName("img")相同;
### 文档写入
将输出流写入到网页中,有4个方法;
- write(string) 原样写入
- writeIn(string) 在字符串的末尾添加一个换行符(\n);
- open()
- close()
write和writeIn
Document
now time is:
open()和close()分别用于打开和关闭网页的输出流;如果是加载期间使用write()或者writeIn()方法,则不需要用到这两个方法;
### 文档的子节点
- document.documentElement;//拿到这个标签;
- document.body//拿到body这个层的标签;
主要就是这两个方法的,当然也可以用别的方法来获取同样的效果的;
比如
document.childNodes[0];
document.firstChild;
这两个都可以获取到html标签;
### 文档信息
- document.title 设置文档的标题
- document.URL 获取或者设置完整的URL
- document.domain 获取或者设置域名
- document.referrer 取得来源页面的URL
### DOM一致性检测
- hasFeartrue()
# Element类型
- HTML元素
- 操作特性
- attributes属性
- 创建元素
Element和Document类型一样,都是非常使用的类型;
Element的类型,nodeType的值为1、nodeName为元素的标签名,nodeValu是null;如果要访问元素的标签名,可以使用nodeName属性,也可以使用tagName属性;两个属性返回相同的值;
这是一个ID为test的div内容
返回的标签名是大写的DIV;一般比较都会转成小写然后比较;如下;
if(test.tagName.toLowerCase()=="div"){
console.log("目标的元素是div标签,开始执行代码");
}
### HTML元素
所有的HTML元素都是由HTMLElement类型表示,如果不是直接通过这个类型,也是通过它的子类型表示;可以输出看下,HTMlElement类型继承自ELement类型的;
这是一个ID为test的div内容
输出的图片的如下;

每个HTML元素都存在下面的标准特性
- id 元素在文档中的唯一标识符
- title 有关元素的附加说明信息,鼠标放上去会显示,(以前我以为只有a标签才有,其实是都有的)
- lang 元素内容的语言代码,很少使用
- dir 语言的方向,值为ltr或者rtl,很少使用(left-to-right和right-to-left);rtl可以起到右对齐的效果;
- className 与元素的class特性对应,是元素指定的CSS类,没有将这个属性命名为class,是因为class是ECMAscript的保留字;【*】
这是一个ID为test的div内容!!!ddddd.
这是一段文字
### 操作特性
- getAttribute()
- setAttribute()
- removeAttribute()
**getAttribute**:
var test=document.getElementById("test");
console.log(test.getAttribute("id"));//test
console.log(test.getAttribute("className"));//null
console.log(test.getAttribute("class"));//test-class-name
console.log(test.getAttribute("title"));//鼠标放上来的提示
console.log(test.getAttribute("lang"));//en
console.log(test.getAttribute("dir"));//rtl(最后一个字符不能是符号,否则符号在前面显示)
console.log(test.getAttribute("diy-data"));//hehe
这个属性要注意的是,如果想获取到属性,必须先取得这个属性所在的元素;然后再进行相关的Attribute操作;这个属性可以获得自定义属性,根据HTML5规范,自定义的特性应该加上data-前缀进行验证;
转给getAttribute的特性名,与实际的特性名相同,因此要想得到class特性值,应该传入class而不是calssName;
但是有两类特殊的特性,虽然有对应的属性名,但是属性的值与通过getAttribute返回的不同;
- 1、style
- 2、onclick
Document
这是一段测试文字;
通过JS操作DOM的时候,一般不适应getAttribute,而是只使用对象的属性,在取得自定义特性质的情况下,才会使用getAttribute的方法;
**setAttribute**:
接受两个参数,第一个参数是特性名,第二个参数是特性值;如果特性已经存在,setAttribute会以指定的值替换现有的值;如果没有的值会创建并且新增;
通过这个方法设置的特性名会被统一转换为小写的形式;"ID"会最终变成id,"CLASS"会被变为"class";
var test=document.getElementById("test");
test.setAttribute("CLASS","dddddd");//class="dddddd"
**removeAttribute**:
彻底删除元素的特性,调用这个方法不仅清除特性的值,而且也会从元素中完全删除特性;(IE6不支持)
### 创建元素,
document.creatElement()方法,可以创建新元素,接受一个参数,就是要创建的元素,参数可以是标签名
- div
一般都使用标签名;
创建的元素属于游离状态,还没有被添加到文档树中,因为新建的元素并不会马上看到,可以使用appendChild,inserBefore,replaceChild()方法,
var test=document.getElementById("test");
var creatEle=document.createElement('p');
creatEle.id="test-id";
creatEle.className="class-test";
creatEle.innerHTML="innerHTML";
test.appendChild(creatEle);
** 借助createDocumentFragment创建元素 **
文档碎片;document fragment在文档没有对应的标记,为了赋值大量数据渲染时的一种节约性能方法;
原理是:创建大量元素的时候,把元素都先放在文档碎片里,等元素创建添加完,把文档碎片统一插入到指定的元素中;
> 类似与我们生活中,发快递的时候,快递公司通过三轮车把所有的件搜收集起来,然后再统一拉回仓库去发件;
代码如下:
# Text类型的方法
- document.createTextNode() 创建新文本节点
- normalize() 相邻文本节点合并
- splitText() 分割文本节点
**document.createTextNode()**
创建新文本节点,接收一个参数,要插入节点中的文本,(作为参数的文本将按照HTML或者XML的格式进行编码)
var ele=document.createElement("div");
var textNode=document.createTextNode('hello word');
var anotherTextNode = document.createTextNode("lee!");
ele.className="message";
ele.appendChild(textNode);
ele.appendChild(anotherTextNode);
document.body.appendChild(ele);
如果两个文本节点是相邻的同胞节点,那么这两个节点中的文本就会连起来显示,中间不会有空格。
**normalize**
如果在一个包含两个或多个文本节点的父元素上调用 normalize() 方法,则会将所有文本节点合并成一个节点,结果节点的 nodeValue 等于将合并前每个文本节点的 nodeValue 值拼接起来的值。
var ele=document.createElement("div");
var textNode=document.createTextNode('hello word');
var anotherTextNode = document.createTextNode("lee!");
ele.className="message";
ele.appendChild(textNode);
ele.appendChild(anotherTextNode);
document.body.appendChild(ele);
console.log("childNodes的长度:"+ele.childNodes.length+",第一个节点值是"+ele.firstChild.nodeValue);//childNodes的长度:2,第一个节点值是hello word
ele.normalize();
console.log("childNodes的长度:"+ele.childNodes.length+",第一个节点值是"+ele.firstChild.nodeValue);//childNodes的长度:1,第一个节点值是hello wordlee!
**splitText()**
和normalize()相反的方法;按照指定的位置分割 nodeValue 值。
- 原来的文本节点将包含从开始到指定位置之前的内容;(不包含所传的索引)
- 新文本节点将包含剩下的文本。
var ele=document.createElement("div");
var textNode=document.createTextNode('hello word');
ele.className="message";
ele.appendChild(textNode);
document.body.appendChild(ele);
console.log("childNodes的长度:"+ele.childNodes.length+",第一个节点值是"+ele.firstChild.nodeValue);//childNodes的长度:2,第一个节点值是hello word
var newNode=ele.firstChild.splitText(2);
console.log(ele.childNodes.length);//2
console.log(ele.firstChild.nodeValue);//he
console.log(newNode.nodeValue);//llo word
# 精华总结
- tagName 获取元素标签的名称
- className 获取或者设置元素class属性的值
-
- 可以通过className获取test1,也可以把这个值进行修改;
- oDiv.className="test2",此时div的calss就变为test2了,注意,这里的修改会覆盖原来的所有属性;
- style 获取或者设置元素的行内样式,在获取的时候要注意,只能获取行内上写的样式,非行内样式不能获取;
- oDiv.style.backgroundColor="red";就是设置元素的行内北京颜色是红色;
- window.getComputerStyle 获取元素所有经过计算的样式(只要在页面中显示出来,那么该元素的样式都是经过计算的)这个方法,不兼容,一般是下面这种处理
- window.getComputerStyle?window.getComputedStyle(ele,null)[attr]:ele.currenStyle[attr]
- document.creatElement() 创建一个元素节点,例如document.creatElement("div")就是创建一个div元素
- document.creatDocumentFragment() 创建文档碎片