# 浏览器:文档,事件,接口
# DOM 相关
对于特定的 DOM 节点,我们可以通过导航属性访问其相关的节点
这些属性主要分为两组:
- 对于所有节点:
parentNode
,childNodes
,firstChild
,lastChild
,previousSibling
,nextSibling
。 - 仅对于元素节点:
parentElement
,children
,firstElementChild
,lastElementChild
,previousElementSibling
,nextElementSibling
。
兄弟节点相关问题
如果 elem 是任意一个 DOM 元素节点……
elem.lastChild.nextSibling 值一直都是 null,这个判定是不是真的?
elem.children[0].previousSibling 值一直都是 null,这个判定是不是真的?
1、这是真的,因为 elem.lastChild 就是最后一个节点,他没有 nextSibling
2、错误,因为 elem.children[0] 为其第一个子元素,它前面可能存在非元素节点,
因此其 previousSibling 可能为一个文本节点
2
3
4
5
6
7
# 搜索
除了 getElementsBy*
和 querySelector*
方法进行搜索外,querySelectorAll
返回的是一个静态的集合。
我们可以使用 elem.matches(css) (opens new window) 来检查 elem
是否与给定的 CSS 选择器匹配,返回 true
或 false
<a href="http://example.com/file.zip">...</a>
<a href="http://ya.ru">...</a>
<script>
// 不一定是 document.body.children,还可以是任何集合
for (let elem of document.body.children) {
if (elem.matches('a[href$="zip"]')) {
alert("The archive reference: " + elem.href );
}
}
</script>
2
3
4
5
6
7
8
9
10
11
elem.closest(css)
方法会查找与 CSS 选择器匹配的最近的祖先
<h1>Contents</h1>
<div class="contents">
<ul class="book">
<li class="chapter">Chapter 1</li>
<li class="chapter">Chapter 1</li>
</ul>
</div>
<script>
let chapter = document.querySelector('.chapter'); // LI
alert(chapter.closest('.book')); // UL
alert(chapter.closest('.contents')); // DIV
alert(chapter.closest('h1')); // null(因为 h1 不是祖先)
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
elemA.contains(elemB)
可以检查子级与父级之间关系的方法。
DOM
节点类的继承关系,如下所示
针对一个节点,可以通过 tagName
或者 nodeName
来读取其元素节点名称或节点名称。
# 特性和属性
如果一个特性不是标准的,那么就没有相对应的 DOM 属性。如 type
是 <input>
的一个标准的特性,但对于 <body>
来说却不是。
所有的特性可以通过以下方法来进行访问:
elem.hasAttribute(name)
— 检查特性是否存在。elem.getAttribute(name)
— 获取这个特性值。elem.setAttribute(name, value)
— 设置这个特性值。elem.removeAttribute(name)
— 移除这个特性elem.attributes
— 读取所有特性,其返回具有name
和value
属性的对象集合
特性名称是大小写不敏感的,所有以 “data-” 开头的特性均被保留供程序员使用。它们可在 dataset
属性中使用。
# 元素滚动
元素滚动相关属性的整体图片如下图:
注意:除了 scrollTop
和 scrollLeft
可以改变外,其他属性都为只读属性
CSS width 与 clientWidth 的不同点
clientWidth
值是数值,而getComputedStyle(elem).width
返回一个以px
作为后缀的字符串。getComputedStyle
可能会返回非数值的 width,例如内联(inline)元素的"auto"
。clientWidth
是元素的内部内容区域加上 padding,而 CSS width(具有标准的box-sizing
)是内部内容区域,不包括 padding。- 如果有滚动条,并且浏览器为其保留了空间,那么某些浏览器会从 CSS width 中减去该空间(因为它不再可用于内容),而有些则不会这样做。
clientWidth
属性总是相同的:如果为滚动条保留了空间,那么将减去滚动条的大小。
# window 滚动
几何:
文档可见部分的 width/height(内容区域的 width/height):
document.documentElement.clientWidth/clientHeight
整个文档的 width/height,其中包括滚动出去的部分:
let scrollHeight = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight );
1
2
3
4
5
滚动:
- 读取当前的滚动:
window.pageYOffset/pageXOffset
。 - 更改当前的滚动:
window.scrollTo(pageX,pageY)
— 绝对坐标,window.scrollBy(x,y)
— 相对当前位置进行滚动,elem.scrollIntoView(top)
— 滚动以使elem
可见(elem
与窗口的顶部/底部对齐)。
# 事件简介
分配事件处理程序有以下三种方式:
HTML 特性(attribute):
onclick="..."
。这里函数需要添加括号,因为浏览器在读取其属性的时候,会创建如下处理程序button.onclick = function() { sayThanks() }
1
2
3DOM 属性(property):
elem.onclick = function
。方法(method):
elem.addEventListener(event, handler[, phase])
用于添加,removeEventListener
用于移除。
transtionend
和 DOMContentLoaded
等少数事件必须使用第三种方法才可发生作用。无论 addEventListener
怎样,DOM属性的处理程序都会触发,且先于 addEventListener
触发事件。
# 冒泡和捕获
几乎所有事件都会“冒泡”,如 focus
事件就不会冒泡
event.stopPropagation()
阻止事件冒泡,但是当前元素上的其他处理程序都会继续运行。 event.stopImmediatePropagation()
方法,不仅会阻止冒泡,还会阻止当前元素上其他处理程序的执行。
事件被阻止冒泡后,则不会被 addEventListener
所监听。
DOM 事件 (opens new window)标准描述了事件传播的 3 个阶段:
- 捕获阶段(Capturing phase)—— 事件(从 Window)向下走近元素。
- 目标阶段(Target phase)—— 事件到达目标元素。
- 冒泡阶段(Bubbling phase)—— 事件从元素上开始冒泡。
# 阻止浏览器行为
有两种方式来告诉浏览器我们不希望它执行默认行为:
- 主流的方式是使用
event
对象。有一个event.preventDefault()
方法。 - 如果处理程序是使用
on<event>
(而不是addEventListener
)分配的,那返回false
也同样有效。
如果默认行为被阻止,那么 event.defaultPrevented
属性为 true
,否则为 false
# UI 事件
# 鼠标事件
鼠标事件有以下属性:
- 按钮:
button
。 - 组合键(如果被按下则为
true
):altKey
,ctrlKey
,shiftKey
和metaKey
(Mac)。- 如果你想处理
ctrl
,那么不要忘记 Mac 用户,他们通常使用的是Cmd
,所以最好检查if (e.metaKey || e.ctrlKey)
。
- 如果你想处理
- 窗口相对坐标:
clientX/clientY
。 - 文档相对坐标:
pageX/pageY
。
mousedown
的默认浏览器操作是文本选择,如果不想实现该行为,则应该避免它。如想在双击时,避免选中文本,我们可以像以下这么做。
<b ondblclick="alert('Click!')" onmousedown="return false">
在有些网站里我们可以发先我们无法复制页面的内容,这是由于使用了 oncopy
事件,并返回了 false
。
# 鼠标移动
主要有 mouseover
、mouseout
、mousemove
、mouseenter
和 mouseleave
事件
其中主要需要关注的有以下几点:
- 快速移动鼠标可能会跳过中间元素
mouseover/out
和mouseenter/leave
事件还有一个附加属性:relatedTarget
。这就是我们来自/到的元素,是对target
的补充。mouseenter/leave
事件不会冒泡,元素内部与后代之间的转换不会产生影响。但是它们的通用性较差,如果我们想引入事件委托时,它则无法使用
鼠标拖放事件详见文档 (opens new window)