1.节点层级
任何HTML活XML文档都可以用DOM表示为一个由节点构成的层级结构。
document是每个文档的根节点,根节点唯一的子节点是<html>元素,称为 文档元素。
文档元素是文档最外层的元素,每个文档只能有一个文档元素。
HTML页面中,文档元素始终是<html>元素。
1.Node类型
每个节点都有nodeType属性,表示该节点的类型。
Node类型上定义的12个数值常量。
1.nodeName 和 nodeValue
这两个属性保存有关节点的信息,这两个属性的值完全取决于节点类型。
对元素而言,nodeName始终等于元素的标签名,nodeValue始终是null
2.节点关系
每个节点都有
childNodes : 子节点列表,类数组。
parentNode :父元素
perviousSibling : 前一个兄弟元素
nextSibling : 后一个兄弟元素
firstChild : 第一个子节点
lastChild : 最后一个子节点
hasChildNodes() : 返回true说明节点有一个或多个子节点
ownerDocument:所有节点都共享的关系,指向代表整个文档的文档节点的指针。
上面这些关系的指针都是只读的。
2、操纵节点
appendChild(): 返回值是新添加的节点。 作用是在childNodes列表末尾添加节点。 如果传入的值是已经存在的节点,那么这个节点会从原来的地方转移到新位置。
insertBefore() : 参数是 要插入的节点 和 参照节点。 会将要插入的节点变成参照节点的前一个同胞节点并返回。 如果参照节点是null,那么添加在末尾。
replaceChild(): 参数是要插入的节点 和要替换的节点 。会将要替换的节点替换成要插入的节点 并返回。
removeChild(): 直接移除某节点,并返回这个节点。
cloneNode(): 会返回与调用它的节点一模一样的节点。 参数 接收一个布尔值,表示是否深拷贝。
【cloneNode() 只会赋值HTML元素,以及可选择复制子节点,但不会复制添加在上面的事件或其他js属性】
normalize() : 会检测这个节点的所有后代,如果发现空文本节点,就删除,如果两个同胞节点相邻,就合并成一个文本节点。
2.Document类型
document类型表示文档节点。文档对象document是HTMLDocument的实例,表示整个HTML页面。document是window对象的属性,是全局对象。
document类型的节点特征:
- nodeType 是9
- nodeName是"#document"
- nodeValue 是null
- parentNode 是 null
- ownerDocument 是null
- 子元素是……
1.文档子节点
文档只有一个子节点,<html>元素,可以通过文档节点的子节点访问。
也可以有一些快速访问。
let html = document.documentElement ; ——> <html> console.log( html === document.childNodes[0] ) // true console.log( html === document.firstChild ) // true
<body>元素 快速访问
let body = document.body ——> <body>
<!doctype> 元素 快速访问
let doctype = document.doctype; ——> <!doctype>
2.文档信息
(1) title属性,是<title>元素中的文本,显示在浏览器窗口或者标签页标题栏,可读可写。但是修改后的title属性不会改变<title>元素,但会在标题栏上显示
let originTitle = document.title // 读取文档标题 document.title = "修改标题"
(2) URL :包含当前页面完整URL 。
domain:当前页面的域名
referer: 链接到当前页面的那个页面的URL 。 如果当前页面没有来源,则referer 是空字符串。
这三个信息其实可以在请求的HTTP头部中获取。
let url = document.URL; let domain = document.domain; let referer = document.referer;
其中,domain可以设置。限制是 1.只能给这个属性设置URL中包含的值。 2.只能放松,不能再收紧。
3.定位元素
(1) getElementById() 如果找到了返回元素,没找到返回Null。 如果页面中存在多个id相同的元素,那么只会返回文档中出现的第一个元素。
(2) getElementsByTagName() 根据标签名返回元素列表,(其实是HTMLCollection对象,属于实时列表)
HTMLCollection对象有个额外方法 : namedItem();通过标签的name来获取某项的引用。
<img src="myImage.gif" name="myImage"> let myImage = document.getElementsByTagName().namedItem('myImage'); // 等价 let myImage = document.getElementsByTagName()['myImage'];
如果想取得文档所有元素,可以给getElementsByTagName()传入 * ,顺序是在页面中出现的顺序。
(3) getElementsByName()
4.特殊集合
document.anchors:文档中所有带name属性的<a>元素
document.forms :文档中所有<form>元素
document.images : 文档中所有<img> 元素
document.links : 文档中所有带href属性的<a>元素
3.Element类型
Element表示XML或HTML元素,对外暴露出访问元素标签名,子节点和属性等。
Element类型节点特征:
- nodeType 是1
- nodeName是元素标签名
- nodeValue 是null
- parentNode 是 Document或者Element
可以通过nodeName或者tagName属性来获取元素标签名。
<div id="myDiv"> </div> let div = document.getElementById('myDiv'); console.log(div.tagName) // 'DIV' console.log(div.tagName === div.nodeName); // true
Ps: div.tagName返回的是DIV 。 HTML中,元素标签名 都会以全大写来表示,XML中会和源代码中一致。所以一般都会 if(element.tagName.toLowerCase() === 'div') 这样表示
1.HTML元素
所以HTML元素都有的标准属性
- id
- title
- lang
- dir 语言的书写方向 ltr从左到右,rtl从右到左
- className
这些属性都是可读可写的。
2.取得属性
每个元素都有零个或多个属性,通常用于给元素或其内容附加更多信息。
getAttribute() 可以获取到正式属性,也可以获取到自定义属性。如果给的属性不存在,返回null。 且属性名不区分大小写。
setAttribute()
removeAttribute()
通过getAttribute()访问属性和通过DOM对象访问属性的区别:
- 通过getAttribute()可以访问自定义属性,通过DOM对象只能访问公认属性
- 通过DOM对象访问的属性有两个返回值和getAttribute()取得的值不一样:
-
- style: getAttribute('style')返回的是css字符串,DOM元素访问 dom.style 返回的是一个CSS对象
- 事件处理程序(事件属性) 。 如onclick 。getAttribute('onclick')返回的是字符串形式的源代码。 DOM元素访问dom.onclick 返回的是js函数。
所以考虑到以上差异,开发时一般使用DOM对象属性。getAttribute()一般用来取自定义属性的值。
3.设置属性
setAttribute('key','value') 如果属性已经存在,会替换原来的值,如果不存在,会创建该属性。
可以设置HTML属性,也可以设置自定义属性。
直接操作DOM对象的属性也可以进行赋值。注意:在DOM对象上添加自定义属性 并不会起作用。
removeAttribute() 不仅是清除属性的值,而是会将整个属性完全从元素中去掉。
4.attributes属性
Element类型是唯一使用attributes属性的DOM节点类型。 attributes属性包含一个NamedNodeMap实例。
一般不用,最有用的应用场景是需要迭代元素上所有属性的时候。
5.创建元素
document.createElement() 创建新元素,接收一个参数,即要创建元素的标签名
let div = document.createElement('div');
可以再为它添加属性和子元素等。
div.id = 'myNewDiv';
div.className = 'box';
要把元素添加到文档树,可以使用appendChild(),insertBefore(),replaceChild();
如:
document.body.appendChild(div);
6.元素后代
元素可以拥有任意多的子元素和后代元素。
childNodes 包含元素所有子节点,可能是 元素,文本节点,注释或处理之灵。
不同浏览器在识别节点时会有些差异,比如有些浏览器可能会将空格解析成Text节点。
所以在执行操作时需要先检测一下节点的nodeType
for(let i = 0; i < element.childNodes.length;i++){ if(element.childNodes[i].nodeType === 1){ // 执行操作 } }
4.Text类型
Text节点由Text类型表示,包含按字面解释的纯文本,也可能包含转移后的HTML字符,但不包含HTML代码
Text类型节点具有特征:
- nodeType 是 3
- nodeName是"#text"
- nodeValue 是 节点中包含的文本
- parentNode 是 Element对象
- 不支持子元素
Text节点中的文本可以通过nodeValue属性访问,也可以通过data属性访问。修改其中一个值,另一个也会相应改变。
操作文本节点的方法:
appendData(text)
deleteData(offset,count)
insertData(offset,text)
replaceData(offset,count,text)
splitText(offset)
substringData(offset,count)
1.创建文本节点
document.createTextNode(text)
2.规范化文本节点
normalize()
3.拆分文本节点
splitText()
5.Comment类型
DOM中的注释通过Comment类型表示。
Comment类型节点特征:
- nodeType 是 8
- nodeName是"#comment"
- nodeValue 是 注释的内容
- parentNode 是 Document或Element对象
- 不支持子元素。
创建注释节点:document.createComment()