所有节点类型的实例的原型链:
Node.prototype->EventTarget.prototype->Object.prototype;
某节点.childNodes.__proto__->NodeList.prototype->Object.prototype;
通过某用法(比如getElementsByTagName,getElementsByClassName,getElementsByTagNameNS,document.forms等)获取的节点集合.__proto__->HTMLCollection.prototype->Object.prototype
某类型实例.__proto__->某类型.prototype->Node.prototype->EventTarget.prototype->Object.prototype;
document.__proto__->HTMLDocument.prototype->Document.prototype->Node.prototype->EventTarget.prototype->Object.prototype;
documentElement.prototype->HTMLHtmlElement.prototype->HTMLElement.prototype->Element.prototype->Node.prototype->EventTarget.prototype->Object.prototype;
document.body->HTMLBodyElement.prototype->HTMLElement.prototype->Element.prototype->Node.prototype->EventTarget.prototype->Object.prototype;
html.attributes.__proto__->NamedNodeMap.prototype->Object.prototype;
某特性节点.__proto__->Attr.prototype->Node.prototype->EventTarget.prototype->Object.prototype
div.style.__proto__->CSSStyleDeclaration.prototype->Object.prototype;
某文本节点.__proto__->Text.prototype->CharacterData.prototype->Node.prototype->EventTarget.prototype->Object.prototype;
Comment类型实例.__proto__->Comment.prototype->CharacterData.prototype->Node.prototype->EventTarget.prototype->Object.prototype;
文档片段实例.__proto__->DocumentFragment.prototype->Node.prototype->EventTarget.prototype->Object.prototype
document.doctype.__proto__->DocumentType.prototype->Node.prototype->EventTarget.prototype->Object.prototype;
该类型只针对基于XML文档:CDATASection实例._proto__->CDATASection.prototype->Text.prototype->CharacterData.prototype->Node.prototype->EventTarget.prototype->Object.prototype;
document.implementation.__proto__->DOMImplementation.prototype->Object.prototype;
ele.dataset.__proto__->DOMStringMap.prototype->Object.prototype;
文档对象模型DOM的核心是以节点为基本单位组成的树结构,整个树结构对应着整个页面的文档,每一个树节点代表着文档中的一个单位的文档内容。同时DOM还是跨平台的编程接口,还支持XML和XHTML类型的文档。有多种节点类型,常用的节点类型有以下几种。
Node节点类型:
nodeType:表示节点类型,值为常量数字,有12种值。
nodeName:节点名字。
nodeValue:节点值。
childNodes:子节点集合,是一个NodeList实例,是类数组,可以中括号或item()访问其子元素,是实时变化的对象;
子节点集合中:
同级前一个节点previousSibling、同级后一个节点nextSibling;
parentNode:父节点;
父节点上的属性和方法:
第一个子节点firstchild、最后一个子节点lastChild;
appendChild(要插入的节点):向子节点的末尾添加节点,并返回插入的节点;元素被添加到文档树中,浏览器会立即将其渲染出来。
insertBefore(要插入的节点,参照节点):向子节点中参照节点前面插入节点,并返回插入的节点;
replaceChild(要插入的节点,要被替换的节点):把子节点中某个节点用要插入的节点替换掉,将被替换的节点从文档中删除并返回;
removeChild(要删除的节点):删除某个节点并将其返回;
hasChildNodes():检测是否有子节点,返回布尔值;与检测length属性是否大于0具有相同作用。
ownerDocument:所有节点都有的一个属性,指向代表整个文档的文档节点的指针。
node.cloneNode(是否深复制):复制节点并将其返回;只会复制html属性,不会复制js属性事件处理程序等。
normalize():格式化、合并子节点中的文本节点。
Document文档节点类型:
Document可以表示HTML页面、XHTML页面或其他XML文档。
文档对象document是HTMLDocument的实例(HTMLDocument继承Document),表示整个HTML页面,document是window对象的属性。
document.documentElemnt指向html元素;document.body指向body元素;document.doctype指向<!doctype>元素;document.title指向<title>元素;document.URL包含当前页面完整的URL地址;document.domain包含页面的域名;document.。referrer包含链接到当前页面的那个页面的URL。
getElementById()、getElementsByTagName():是Document类型提供的两个方法。如果页面中存在多个相同id元素则返回第一个,后者返回一个NodeList,在**html**文档中返回**HTML**Collection对象,在其他文档中就不是**HTML**Collection对象,可能是**XHTML**Collection对象、**XML**Collection对象。**HTML**Collection对象可以看成NodeList在html文档中实现吧。**XML**Collection和NodeList都是是类数组,可以中括号或item()访问其子元素,是实时变化的对象;**XML**Collection还有一个额外的方法namedItem(元素的name属性名),这也是字符串索引在后台调用的方法。传入星号“*”可以获得所有元素。
getElementsByName():获取具有给定name属性的所有元素。
querySelector():通过css选择器,返回匹配该模式的第一个后代元素。
querySelectorAll():通过css选择器,返回匹配该模式的所有后代元素,是一个NodeList静态实例。
matches():通过css选择器,返回是否匹配该模式的布尔值。
getElementsByClassName():通过数个类名,返回匹配该模式的所有后代元素,是一个NodeList实例;
document.activeElement始终包含当前拥有焦点的DOM元素。
Element元素节点类型:document对象上获取元素dom节点的方法也可通过元素节点上调用访问。
document.createElement("元素标签名"):创建元素。
childElementCount:返回子元素数量;
firstChildElement:返回第一个子元素;
lasttChildElement:返回第一个子元素;
同级前一个元素previousElementSibling、同级后一个元素nextElementSibling;
innerHTNL:读取时会返回元素所有后代的HTML字符串,包括元素、注释和文本节点。而在写入时则会用新的内容替代原有节点。主流浏览器通过innerHTML插入<script>标签是不会执行的。
outerHTML:读取时会返回调用它的元素及所有后代元素的HTML字符串。写入时调用他的元素会被写入的子树取代。
innerText、outerText:将innerText赋值给innerText,可以去除所有HTML标签而只剩下文本。
insertAdjacentHTML()、insertAdjacentHTML():他们接受两个参数,要插入标记位置和要插入的HTML或文本。位置参数包括:beforebegin、afterbegin、beforeend、afterend.
scrollIntoView():参数alignToTop是一个布尔值,true窗口滚动后元素的顶部与视口顶部对齐,false窗口滚动后元素的顶部与视口底部对齐。scrollIntoViewOptions是一个选项对象,behavior值为smooth或者auto;block、inline定义垂直方向水平方向的对齐,可取的值为start、center\end、nearest(默认).
元素节点的属性有多种访问的方式:
1.对象属性方式--DOM.属性名
nodeName、tagName属性用来获取元素的标签名,如:DIV。
DOM.className属性名是获取类属性的方式。
获取style属性时返回的是一个对象;
获取事件处理程序时返回的是一段js代码;
无法获取设置自定义属性;
2.语义规范方式:
getAttribute():将"class"传入为参数是获取类属性的方式。获取style和事件处理程序属性时返回的是一段字符串。获取时属性名不区分大小写。
setAttribute():设置时属性名为小写。
removeAttribute():
3.attributes属性集合方式:NamedNodeMap实例,是一个类似NodeList的集合。此种方式在迭代元素属性的场景中很方便。
元素的每一个属性都表示为一个Attr节点,并保存在这个NamedNodeMap对象中,此对象包含下列方法:
getNamedItem(name):返回nodeName属性等于name的节点;element.attributes.getNameItem("id").nodeValue/element.attributes["id"].nodeValue;
removeNamedItem(name):移除nodeName属性等于name的节点;let a= element.attributes.removeNamedItem(a);
setNamedItem(node):向列表中添加node节点,以其nodeName为索引;element.attributes["id"].nodeValue="abc";element.attributes.setNamedItem(a);
item(pos):返回索引位置pos处的节点;
4.直接操作DOM的属性节点方式:
element.getAttributeNode("a").value;
element.setAttributeNode(node);
classList属性是类属性节点对象,是一个新的集合类型DOMTokenList的实例,有length属性、通过item()、中括号取得元素,可以通过此对象操作类:
add(value):向类名列表中添加指定的字符串值value,如果这个值已经存在,则什么也不做。
contains(value):返回布尔值,表示给定的value值是否存在;
remove(value):从类名列表中删除指定的字符串值value;
toggle(value):如果类名列表中已经存在指定的value值,则删除;如果不存在,则添加;
自定义属性:
\<div id="myDiv" data-appId="123" data-myname="xiaoming">\</div>;
let appId = div.dataset.appId;let myName = div.dataset.myname;
div.dataset.appId="345";div.dataset.myname=""zhangsan;
动态脚本\<script\>标签元素:
大多数主流浏览器是允许创建js代码以<script\>标签子节点的方式插入的,但是低版本的ie浏览器是不允许常规DOM访问其子节点,只能通过将字符串格式的js代码赋值给其text属性插入js代码。
通过innerHTML属性创建的<script>元素永远不会被执行。
动态样式<style>标签元素:
css样式在HTML页面中可以通过两个元素加载。link元素用于包含css外部文件,而style元素用于添加嵌入样式。
通过外部文件加载样式是一个异步过程。因此,样式的加载和正在执行的js代码并没有先后顺序。
<style>标签也是ie禁止访问其子节点,其他主流浏览器允许常规DOM访问其子节点,但是ie支持把字符串格式的css代码赋值给style.styleSheet.cssText;如果重复赋值、或者赋空值会导致浏览器崩溃。
Attr属性节点类型:
let attr=document.createAttribute("align");attr.value="left";element.setAttributeNode(attr);element.getAttributeNode("align").value;
Text文本节点类型:具有length属性
document.createTextNode():创建文本节点;
nodeValue、data:访问文本节点的值;
appendData(text):向节点末尾添加文本text;
deleteData(offset,count):从位置offset开始删除count个字符;
insertData(offset,text):在位置offset插入text;
replaceData(offset,count,text):用text替换从位置offset到offset+count的文本;
splitText(offset):在位置offset将当前文本节点拆分为两个文本节点;
substringData(offset,count):提取从位置offset到offset+count的文本;
normalize():格式化、合并子节点中的文本节点。
每一种节点类型都有其增删改查的接口,以便对其进行操作。
使用本节介绍的方法替换子节点可能在浏览器中导致内存问题。比如如果被移出的子树元素中之前有关联的事件处理程序或其他js对象作为元素属性,那他们之间的绑定关系会滞留在内存中。如果这种操作频繁发生,页面的内存占用就会持续攀升。在使用innerHTML、outerHTML、insertAdjacentHTML()之前,最好手动删除要被替换的元素关联的事件处理程序和js对象。
MutationObserver接口用来对DOM节点的修改进行监测,当被监测的内容发生改变时会触发其相应的回调函数。
let observer = new MutationObserver( (mutationRecords,mutationObserver实例) = > a=b+c;);mutationRecords是一个数组,包括多个变化记录对象。
observer.observe(DO节点对象,MutationObserverInit对象);MutationObserverInit对象用来配置监测的DOM节点的范围,如属性、子节点等;
连续修改会生成多个mutationRecords实例,下次回调执行时就会收到包含所有这些实例的数组,顺序为变化事件发生的顺序。
observer.disconnect():不仅会终止此后变化事件回调,也会抛弃已经加入任务队列要异步执行的回调。如果监测多个dom节点,会同时清除对多个节点的监测。此方法不会结束MutationObserver的生命,可以再把它关联到新的节点重新使用。
多次调用observe()方法,可以复用一个MutationObserver对象观察多个不同的目标节点。
被观察子树中的节点被移出子树之后仍然能够触发变化事件。
observer.takeRecords():可以清空记录队列,取出并返回其中的所有MutationObserver实例。
MutationObserver实例与目标节点之间的引用关系是非对称的。MutationObserver拥有对要观察的目标节点的弱引用。因为弱引用,所以不会妨碍垃圾回收程序回收节点。
然而,目标节点却拥有对MutationObserver的强引用。如果目标节点从DOM中被移除,随后被垃圾回收,则关联的MutationObserver也会被垃圾回收。
在DOM树结构中对节点进行遍历的时候是遵循深度优先的规则进行的。同时也有相应的接口方法支持向节点的不同方法移动遍历--父级方向、子集方向、同级前后方向。TreeWalker接口支持所有方向的移动,NodeIterator接口支持支同级前后方向的移动。
以上所有内容的操作都是以节点单位为边界进行的,有时需要以跨节点为单位边界进行操作,这时就需要范围对象Range的增删改查方法来实现了。