DOM树
DOM(Document Object Model):文档对象模型。
由于HTML文档被浏览器解析后就是一棵DOM树,要改变HTML的结构,就需要通过JavaScript来操作DOM。

上图就是DOM树,DOM 的最小组成单位叫做节点(node)其中每个节点的都是Node类型:
Document:整个文档树的顶层节点DocumentType:doctype标签(比如<!DOCTYPE html>)Element:网页的各种HTML标签(比如<body>、<a>等)Attribute:网页元素的属性(比如class="right")Text:标签之间或标签包含的文本Comment:注释DocumentFragment:文档的片段
所有DOM节点对象都继承了Node接口,这是 DOM 操作的基础。
Node接口的属性和方法
对于DOM的操作,最主要归纳于四个字:增、删、改、查。
首先是查:
Document.getElementsByClassName();//返回指定Class name的节点
Document.getElementById();//返回指定ID的节点
Document.querySelector();//接受一个 CSS 选择器作为参数,返回第一个匹配该选择器的元素节点
Document.querySelectorAll();//返回一个NodeList对象,包含所有匹配给定选择器的节点。
//两种方法获取的节点是有有区别的,document.querySelectorAll方法返回的是一个静态集合。DOM内部的变化,并不会实时反映在该方法的返回结果之中。

在得到相应Node节点时候, Node节点本身也有一些重要属性:
nodeName//返回节点类型,重要的返回的值有大写的HTML元素名, #text,#document
nodeType//属性返回一个整数值,表示节点的类型。文档节点(document):9,元素节点(element):1;文本节点(text):3
nodeValue//返回一个字符串,表示当前节点本身的文本值,只有文本节点(text)、注释节点(comment)和属性节点(attr)有返回结果,其他节点都返回null
textContent//属性自动忽略当前节点内部的 HTML 标签,返回所有文本内容。//而innerText在IE下会忽略隐藏(例如css,style),同时也会重置写入。
兄弟关系:Node.nextSibling;Node.previousSibling//会获取到文本节点(例如回车)
父子关系:node.parentNode;node.childNodes;node.firstChild;node.lastChild
其中node.childNodes属性返回一个伪数组的对象(NodeList集合);伪数组内的值是动态变化的,回车也会充当文本体现出来。
Node方法:
Node.appendChild()//将其作为最后一个子节点,插入当前节点Node.hasChildNodes()//返回一个布尔值,表示当前节点是否有子节点Node.cloneNode()//克隆一个节点,接受参数true为表示同时克隆子节点Node.insertBefore(newNode, referenceNode)//将某个节点插入父节点内部的指定位置。Node.removeChild()用于从当前节点移除该子节点,被移除的节点依然存在于内存之中,但不再是 DOM 的一部分。Node.replaceChild(newChild, oldChild)//替换当前节点的某一个子节点Node.contains()Node.isEqualNode()//用于检查两个节点是否相等,指的是两个节点的类型相同、属性相同、子节点相同。Node.isSameNode()//表示两个节点是否为同一个节点。Node.normalize()
Document节点的属性和方法:
Document节点属性有:
document.hidden返回一个布尔值,表示当前页面是否可见。配合document.visibilityState(返回文档的可见状态)使用。
document.referrer表示当前文档的访问者来自哪里,可用于网站图片防盗链,流量,DDOS。
- document.characterSet;document.title;document.domain;document.styleSheets;document.scripts;document.plugins
- document.images;document.links;document.forms;
- document.doctype;document.documentElement//返回HTML;
- document.body;document.head;document.scrollingElement;document.fullscreenElement
Document节点方法有:
DOM的增:
Document.createElement() // 创建元素
Document.createTextNode() //创建一个新的文本节点
Node.appendChild()//插入当前节点
Element.classList.add() //添加指定的类值class
Document.write();Document.writeIn() // 将文本字符串写入打开的文档流;document.write()和writeIn()的区别是前者没有换行,而后者有换行。但要防止异步、setTimeOut导致冲洗掉整个文档。
DOM的删:
Element.removeAttribute() // 从元素中删除指定的属性
Element.removeChild()// 删除子元素
ChildNode.remove() // 删除元素
Child.parentNode.removeChild(child) // 不确定父元素时可这样删除子元素
Element.classList.remove() // 移除元素中一个或多个类名
DOM的改:
Node.replaceChild() // 替换子节点
style.property = new style // 修改元素CSS属性值
Element.setAttribute() // 设置或者改变指定属性并指定值
Node.innerText // 修改元素文本内容
Element.innerHTML // 设置或获取描述元素后代的HTML语句
DOM事件模型
在2000年11月,DOM标准在Level 2中加入了Events事件模型,后期的Level 3也并未对Events进行修改。
以事件监听为例:
1 | <button id="xxx">点击</button> |
DOM事件流包括三个阶段。
事件捕获阶段
处于目标阶段
事件冒泡阶段

xxx.addEventListener('chick',function(){},false): 事件监听默认为false,冒泡阶段触发。当值为true时,捕获阶段触发;处于捕获阶段的事件会比冒泡阶段先发生。

实现一个点击弹出popover
要求
- 点击按钮弹出浮层
- 点击别处关闭浮层
- 点击浮层时,浮层不得关闭
- 再次点击按钮,浮层消失

参考文献: