1 DOM简介
DOM(document object model 文档对象模型)是W3C组织推荐的处理可扩展标记语言(HTML或xml)的标准接口,是中立于平台和语言的接口,它允许程序和脚本动态地访问和更新文档地内容、结构和样式,对网页进行增删改查的操作。
- 核心DOM:可操作一切结构化文档的 API ,包括 HTML 和 XML (万能但繁琐)
- HTML DOM:专门操作 HTML 文档的简化版 DOM API ,仅对常用的复杂的 API 进行了简化(简单但不是万能)
DOM树
-
文档:一个页面就是一个文档,在DOM中用
document
表示。 -
元素:页面中所有的标签都是元素,在DOM中用
element
表示。 -
节点:网页中所有的内容都是节点(标签、属性、文本、注释等),在DOM中用
node
表示。HTML DOM树中的所有节点均可通过JS进行访问,所有HTML元素(节点)均可被修改,也可以创建或删除。
DOM将以上内容都看成对象
2 DOM 获取
-
document.getElementById("id")
按id属性,精确查找一个元素对象(效率非常高)
只能用在document上,用于精确查找一个元素
-
parent.getElementByTagName("tag")
按标签名查找(查找指定parent元素下的所有标签为tag的子代元素)
1 可用在任意父元素上
2 不仅查直接子节点,而且查所有子代节点
3 返回一个动态集合[与数组类似](即使找到一个元素,也返回集合,必须用[0],取出唯一元素) -
document.getElementByName('name属性值')
通过name属性查找(可以返回DOM树中具有指定name属性值的所有子元素的集合)
-
parent.getElementByClassName('class')
通过class查找,查找parent元素下指定class属性的元素
有兼容性问题:IE9+
-
parent.querySelector("selector")
通过CSS选择器查找(只找一个元素)
支持一切CSS中的选择器;若选择器匹配有多个,只返回第一个
-
parent.querySelectorAll("selector")
通过CSS选择器查找(找多个)【返回的是非动态集合】
特殊获取
document.body
bodydocument.title
title
3 事件
- 事件由事件源、事件类型、事件处理程序三个部分组成。
- 事件源:事件被触发的对象
- 事件类型:如何触发
- 事件处理程序:通过一个函数赋值的方式完成
常见的鼠标事件
onclick
鼠标点击左键触发onmoseover
鼠标经过触发onmouseout
鼠标离开触发onfocus
获得鼠标焦点触发onblur
失去鼠标焦点触发onmousemove
鼠标移动触发onmouseup
鼠标谈起触发onmousedown
鼠标按下触发
4 DOM 修改
4.1 修改元素的内容
-
element.innerText
【非标准,IE发起】从起始位置到终止位置的内容,但去除了html标签,同时空格和换行也会去掉
-
element.innerHTML
【W3C标准】从起始位置到终止位置的内容,包括html标签,同时保留空格和换行
innerText
不识别html标签,innerHTML
识别html标签- 两者均可读写,可用于获取元素内容
-
element.value
用于修改表单元素的内容
4.2 修改元素的属性
- 自定义属性
- 目的:为了保存并使用数据,有些数据可以保存到页面中二不用保存到数据库中。
- HTML5中规定,自定义属性均以data-开头作为属性名并且赋值。
读取属性值
//方法一:先获得属性节点对象,再获得节点对象的值
var attrNode=element.attributes[下标/属性名];
var attrNode=element.getAttributeNode(属性名);
//此时attrNode.value表示属性值
//方法二:直接获取属性值1
var value=element.getAttribute("属性名");
//HTML5中新增 举例自定义属性名为data-index
var value=element.dataset.index;//或者element.dataset['index']
//方法三:直接获取属性值2
var value=element.属性;
直接获取属性值的两种方法的区别
element.getAttribute('属性');
主要获得自定义的属性(标准)element.属性
主要获取内置属性值(元素本身自带的属性)
修改属性值
element.setAttribute("属性名",value);
element.属性名='……';
//举例
var a1=document.getElementById("a1");
a1.setAttributeNode("name",a1);
a1.name='a';
利用DOM可以操作的表单元素的属性:type、value、checked、selected、disabled
判断是否包含指定属性
var bool=elem.hasAttribute("属性名");
(返回值为boolean类型)
移除属性
elem.removeAttribute("属性名");
4.3 修改元素样式
-
element.style.属性名
行内样式操作【权重较高】注意:属性名要去横线,变驼峰
-
element.className
类名样式操作将样式内容撰写在CSS中,通过直接修改类名的方式来变化样式
5 节点操作
- 利用节点层级关系获取元素
- 利用父子兄节点关系获取元素
- 逻辑性强,但兼容性较差
5.1 节点概述
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
节点类型
- 元素节点 nodeType 为 1
- 属性节点 nodeType 为 2
- 文本节点 nodeType 为 3
在实际过程中,节点操作主要操作的是元素节点。
5.2 节点层级
利用DOM树可以把节点分为不同的层级关系,常见的是父子兄的层级关系。
-
父节点
node.parentNode
得到离元素最近的父节点如果找不到父节点就返回
null
-
子节点
-
parentNode.childNodes
【标准】返回包含指定节点的子节点的集合,该集合为即时更行的集合
【注意:返回值中包含了所有的子节点,包括元素节点、文本节点等。若只想要获得其中的某一类型的节点,则需要专门处理。因此一般不提倡使用
parentNode.childNodes
】 -
parentNode.children
【非标准】是一个只读属性,返回所有的子元素节点。
只返回子元素节点,其余节点不返回
-
parentNode.firstChild
返回第一个子节点【包含所有节点】,找不到就返回
null
。 -
parentNode.lastChild
返回最后一个子节点【包含所有节点】,找不到就返回
null
。 -
parentNode.firstElementChild
返回第一个子元素节点,找不到就返回
null
。 -
parentNode.lastElementChild
返回最后一个子元素节点,找不到就返回
null
。
其中,
parentNode.firstElementChild
和parentNode.lastElementChild
两个方法有兼容性问题,IE9以上才支持。因此,常用
parentNode.children[0]
和parentNode.children[parentNode.children.length-1]
来表示第一个子元素节点和最后一个子元素节点。 -
-
兄弟节点
-
node.nextSibling
返回当前元素的下一个兄弟节点【包含所有节点】,找不到则返回
null
。 -
node.previousSibling
返回当前元素的上一个兄弟节点【包含所有节点】,找不到则返回
null
。 -
node.nextElementSibling
返回当前元素的下一个兄弟元素节点,找不到则返回
null
。 -
node.previousElementSibling
返回当前元素的上一个兄弟元素节点,找不到则返回
null
。
同样,
node.nextElementSibling
和node.previousElementSibling
两个方法有兼容性问题,IE9以上才支持。因此一般采用封装兼容性函数解决
function getNextElementSibling(element){ var el=element; while (el=el.nextSibling){ if(el.nodeType==1){ return el; } } return null; }
-
文档片段
内存中,临时保存多个平级子元素的虚拟父元素,用法和普通父元素完全一样
var frag=document.creatDocumentFragment();//创建片段
frag.appendChild(child);//将子元素临时添加到frag中
parent.appendChild(frag);//将frag追加到页面
强调:append之后,frag自动释放,不会占用元素
5.3 创建、添加和删除节点
-
创建节点
document.createElement('tagName')
创建由tagName(元素名)的HTML元素。
因为这些元素原先并不存在,是根据我们的需求动态生成的,所以我们也成为动态创建元素节点。
-
添加节点
-
node.appendChild(child)
将一个节点添加到指定父节点(node)的子节点列表末尾。类似于CSS中的after伪元素。
-
node.insertBefore(child,指定元素)
将一个节点添加到指定父节点(node)的指定子节点前面。类似于CSS中的before伪元素。
-
-
删除节点
node.removeChild(child)
从DOM中删除一个子节点,并返回删除的节点。
5.4 复制节点(克隆节点)
-
node.cloneNode()
返回调用该方法的节点的一个副本,也称为克隆节点/拷贝节点。
注意:
node.cloneNode()
如果括号参数为空或者false,则是浅拷贝,只克隆复制节点本身,不克隆里面的子节点,即复制标签不复制里面的内容。
node.cloneNode(true)
如果括号参数为true,则是深度拷贝,克隆复制节点本身和里面所有的子节点,即复制标签且复制里面的内容。
*5.5 三种动态创建元素的区别
-
document.write()
直接将内容写入页面的内容流,但如果文档流过程执行完毕(页面加载完成)再执行,则会导致页面重绘。
-
element.innerHTML
将内容写入某个DOM节点,不会导致页面全部重绘。
创建多个元素的效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂。
-
document.createElement()
创建多个元素时效率略低,但是结构更加清晰。