- A+
1. DOM简介
1. 1 什么是DOM
文档对象模型(Document Object Model,简称 DOM),是 W3C组织推荐的处理可扩展标记语言(HTML 或者XML)的标准编程接口。
1.2 DOM树
文档:一个页面就是一个文档,DOM中使用 document 表示
元素:页面中的所有标签都是元素,DOM 中使用 element 表示
节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示
DOM 把以上内容都看做是对象
2. 获取元素
2.1 根据ID获取
document.getElementById('id');
使用 console.dir() 可以打印我们获取的元素对象,更好的查看对象里面的属性和方法
2.2 根据标签名获取
document.getElementsByTagName('标签名');
得到的是一个对象的集合(伪数组)
element.getElementsByTagName('标签名');
父元素必须是单个对象(必须指明是哪一个元素对象)。获取的时候不包括父元素自己
2.3 根据HTML5 新增的方法获取
document.getElementsByClassName(‘类名’);// 根据类名返回元素对象集合
document.querySelector('选择器'); // 根据指定选择器返回第一个元素对象
document.querySelectorAll('选择器'); // 根据指定选择器返回
querySelector
和querySelectorAll
里面的选择器需要加符号
比如:document.querySelector('#nav');
2.4 获取特殊元素(body,html)
doucumnet.body // 返回body元素对象
document.documentElement // 返回html元素对象
3. 事件基础
3.1 事件三要素
- 事件源 (谁)
- 事件类型 (什么事件)
- 事件处理程序 (做啥)
3.2 鼠标事件
4. 操作元素
4.1 改变元素内容
element.innerText
从起始位置到终止位置的内容, 但它去除 html 标签, 同时空格和换行也会去掉
element.innerHTML
起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行
4.2 常用元素的属性操作
1. innerText、innerHTML 改变元素内容 2. src、href 3. id、alt、title
4.3 表单元素的属性操作
type、value、checked、selected、disabled
4.4 样式属性操作
element.style 行内样式操作
element.className 类名样式操作
JS 里面的样式采取驼峰命名法 比如 fontSize、 backgroundColor
JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高
className 会直接更改元素的类名,会覆盖原先的类名
4.5 总结
4.6 自定义属性的操作
4.6.1 获取属性值
element.属性 // 获取内置属性值(元素本身自带的属性)
element.getAttribute('属性'); // 主要获得自定义的属性(标准),程序员自定义的属性
4.6.2 设置属性值
element.属性 = '值' // 设置内置属性值
element.setAttribute('属性', '值'); // 主要设置自定义的属性(标准)
4.6.3 移除属性
element.removeAttribute('属性'); // 自定义的属性
4.7 H5自定义属性
4.7.1 设置属性
(1)H5规定自定义属性data-开头做为属性名并且赋值
<div data-index="1"></div>
(2)使用 JS 设置
element.setAttribute(‘data-index’, 2)
4.7.2 获取属性
(1)兼容性获取
element.getAttribute(‘data-index’);
(2)H5新增
element.dataset.index
element.dataset['index'] // ie 11才开始支持
5. 节点操作
5.1 节点概述
元素节点 nodeType 为 1
属性节点 nodeType 为 2
文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)
我们在实际开发中,节点操作主要操作的是元素节点
5.2 节点层级
5.2.1 父级节点
node.parentNode
parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
如果指定的节点没有父节点则返回 null
5.2.2 子节点
1. parentNode.childNodes(标准) // 不提倡
返回包含指定节点的子节点的集合,该集合为即时更新的集合,包含了所有的子节点,包括元素节点,文本节点等
2. parentNode.children(非标准) // 各个浏览器支持
只读属性,返回所有的子元素节点,它只返回子元素节点,其余节点不返回
第一个子元素节点:parentNode.chilren[0]
最后一个子元素节点:parentNode.chilren[parentNode.chilren.length - 1]
3. parentNode.firstChild
返回第一个子节点,找不到则返回null。包含所有的节点
4. parentNode.lastChild
返回最后一个子节点,找不到则返回null。包含所有的节点
5. parentNode.firstElementChild // IE9 以上才支持
返回第一个子元素节点,找不到则返回null
6. parentNode.lastElementChild // IE9 以上才支持
返回最后一个子元素节点,找不到则返回null
5.2.3 兄弟节点
1. node.nextSibling
返回当前元素的下一个兄弟节点,找不到则返回null。包含所有的节点
2. node.previousSibling
返回当前元素的上一个兄弟节点,找不到则返回null。包含所有的节点
3. node.nextElementSibling // IE9 以上才支持
返回当前元素下一个兄弟元素节点,找不到则返回null
4. node.previousElementSibling // IE9 以上才支持
返回当前元素上一个兄弟元素节点,找不到则返回null
5.3 创建节点
document.createElement('tagName')
创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点
5.4 添加节点
1. node.appendChild(child)
将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的 after 伪元素
2. node.insertBefore(child, 指定元素)
将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before 伪元素
5.5 删除节点
node.removeChild(child)
从 DOM 中删除一个子节点,返回删除的节点
5.6 克隆节点
node.cloneNode()
如果括号参数为空或者为 false ,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点
如果括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子节点
5.7 三种动态创建元素区别
document.write() element.innerHTML document.createElement()
-
document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,会导致页面全部重绘
-
innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
-
innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
-
createElement() 创建多个元素效率稍低一点点,但是结构更清晰
详情:
[三种创建元素的方式]
[innerHTML 和 createElement 效率对比]
6. 注册事件(绑定事件)
6.1 注册事件概述
6.2 addEventListener
eventTarget.addEventListener(type, listener[, useCapture]);
type
:事件类型字符串,比如 click 、mouseover ,注意这里不要带 on
listener
:事件处理函数,事件发生时,会调用该监听函数
useCapture
:可选参数,是一个布尔值,默认是 false
6.3 attachEvent
eventTarget.attachEvent(eventNameWithOn, callback); // IE8 及早期版本支持
eventNameWithOn
:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
callback
: 事件处理函数,当目标触发事件时回调函数被调用
6.4 注册事件兼容性解决方案
function addEventListener(element, eventName, fn) { // 判断当前浏览器是否支持 addEventListener 方法 if (element.addEventListener) { element.addEventListener(eventName, fn); // 第三个参数 默认是false } else if (element.attachEvent) { element.attachEvent('on' + eventName, fn); } else { // 相当于 element.onclick = fn; element['on' + eventName] = fn; }
7. 删除事件(解绑事件)
7.1 删除事件的方式
(1)传统注册方式
eventTarget.onclick = null;
(2)方法监听注册方式
eventTarget.removeEventListener(type, listener[, useCapture]);
eventTarget.detachEvent(eventNameWithOn, callback);
7.2 删除事件兼容性解决方案
function removeEventListener(element, eventName, fn) { // 判断当前浏览器是否支持 removeEventListener 方法 if (element.removeEventListener) { element.removeEventListener(eventName, fn); // 第三个参数 默认是false } else if (element.detachEvent) { element.detachEvent('on' + eventName, fn); } else { element['on' + eventName] = null; }
8. DOM事件流
事件流描述的是从页面中接收事件的顺序
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流
DOM 事件流分为3个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
注意:
-
JS 代码中只能执行捕获或者冒泡其中的一个阶段
-
onclick
和attachEvent
只能得到冒泡阶段 -
addEventListener(type, listener[, useCapture])
第三个参数如果是true
,表示在事件捕获阶段调用事件处理程序;如果是
false
(不写默认就是false
),表示在事件冒泡阶段调用事件处理 程序 -
实际开发中我们很少使用事件捕获,我们更关注事件冒泡
-
有些事件是没有冒泡的,比如
onblur
、onfocus
、onmouseenter
、onmouseleave
-
事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件
9. 事件对象
9.1 什么是事件对象
eventTarget.onclick = function(event) {} eventTarget.addEventListener('click', function(event) {}); // 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
官方解释:event
对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态
简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event
,它有很多属性和方法
9.2 事件对象的使用语法
eventTarget.onclick = function(event) {} eventTarget.addEventListener('click', function(event) {});
event
是个形参,系统帮我们设定为事件对象,不需要传递实参过去
当我们注册事件时,event
对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)
9.3 事件对象的兼容性方案
e = e || window.event;
9.4 事件对象的常见属性和方法
10. 阻止事件冒泡
10.1 阻止事件冒泡的两种方式
-
标准写法:利用事件对象里面的
stopPropagation()
方法e.stopPropagation();
-
非标准写法:IE 6-8 利用事件对象
cancelBubble
属性e.cancelBubble = true;
10.2 阻止事件冒泡的兼容性解决方案
if (e && e.stopPropagation) { e.stopPropagation(); } else { window.event.cancelBubble = true; }
11. 事件委托(代理、委派)
事件委托也称为事件代理, 在 jQuery 里面称为事件委派
原理:
不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点
<ul> <li>123</li> <li>123</li> <li>123</li> <li>123</li> <li>123</li> </ul> // 给 ul 注册点击事件,然后利用事件对象的 target 来找到当前点击的 li,因为点击 li,事件会冒泡到 ul 上, ul 有注册事件,就会触发事件监听器
作用:
只操作了一次 DOM ,提高了性能
12. 常用的鼠标事件
12.1 鼠标事件
禁止鼠标右键菜单:
document.addEventListener('contextmenu', function(e) { e.preventDefault(); });
禁止鼠标选中:
document.addEventListener('selectstart', function(e) { e.preventDefault(); });
12.2 鼠标事件对象
13. 常用的键盘事件
13.1 键盘事件
注意给文档document
添加键盘事件
onkeypress
和前面2个的区别是,它不识别功能键,比如左右箭头,shift
等
13.2 键盘事件对象
onkeydown
和onkeyup
不区分字母大小写,onkeypress
区分字母大小写