Note 2
tabindex & 让 div
具有 focus
和 blur
事件
tabindex
全局属性 指示其元素是否可以聚焦,以及它是否/在何处参与顺序键盘导航(通常使用Tab键,因此得名)。 div设置样式时,可正常使用 :hover
设置悬浮样式,但无法使用 :focus
设置聚焦样式 <div>
本身没有 @blur
和 @focus
事件,可以通过添加 tabindex
属性:
<div tabindex="-1"></div>
TIP
可以使用在任何元素上,不管元素默认是否支持聚焦
tabindex
接受一个整数作为值,具有不同的结果,具体取决于整数的值:
tabindex = 负值(通常是tabindex = "-1")
表示元素是可聚焦的,但是不能通过键盘导航来访问到该元素,用 JS
(例如:@focus
)做页面小组件内部键盘导航的时候非常有用。
tabindex="0"
表示元素是可聚焦的,并且可以通过键盘导航来聚焦到该元素,它的相对顺序是当前处于的 DOM
结构来决定的。(访问的顺序是按照元素在文档中的顺序来focus
,即使采用浮动改变了页面中显示的顺序,依然是按照html文档中的顺序来定位。)
tabindex = 正值
- 表示元素是可聚焦的,并且可以通过键盘导航来访问到该元素;它的相对顺序按照
tabindex
的数值递增而滞后获焦。如果多个元素拥有相同的tabindex
,它们的相对顺序按照他们在当前DOM
中的先后顺序决定。 - 优先级大于
tabindex=0
,在tabindex>=1
时,数字越小,优先级越低。
tabindex
的聚焦顺序:
- 在可聚焦元素中,正整数数值越大,顺序越往后,正整数数值的节点顺序比
0
值的节点靠前。 - 在可聚焦元素中,相同
tabindex
数值的节点,根据DOM
节点的先后顺序决定聚焦顺序。
TIP
如果我们在 <div>
上设置了 tabindex
属性,它的子元素内容不能使用箭头键来滚动, 除非我们在内容上也设置 tabindex
。查看这篇 fiddle 来理解 tabindex 的滚动影响
元素 element 分为
focusable
和非focusable
,使用tabindex
可以改变元素相关的行为
在HTML中有6个元素默认支持聚焦:
- 带
href
属性的<a>
标签 - 带
href
属性的<link>
标签 <button></button>
标签<input />
标签 (排除带有type="hidden"
属性的)<select></select>
标签<textarea></textarea>
标签
以上的元素默认都可以使用 Tab
键,以及 JS
focus()
方法聚焦 例如:
document.querySelector('a').focus()
如何设置 div
元素的 focus
样式? 使用 CSS伪类 :focus-within
:focus-within
是一个 CSS
伪类 ,表示一个元素获得焦点 或 该元素的后代元素获得焦点。换句话说,元素自身或者它的某个后代匹配 :focus
伪类。
/* 当 <div> 的某个后代获得焦点时,匹配 <div> */
div:focus-within {
background: cyan;
}
注
设置 tabindex
后,元素变为可聚焦状态,而当元素被聚焦时,浏览器会在元素周围显示一个蓝色的轮廓,这属于浏览器的默认行为,可通过在元素上添加以下 CSS
样式来隐藏:
div {
outline: none;
}
HTML5 新属性
HTML 属性能够赋予元素含义和语境。
下面的全局属性可用于任何 HTML5 元素。
属性 | 描述 |
---|---|
accesskey | 设置访问元素的键盘快捷键。 |
class | 规定元素的类名(classname) |
contenteditable New | 规定是否可编辑元素的内容。 |
contextmenu New | 指定一个元素的上下文菜单。当用户右击该元素,出现上下文菜单 |
data-* New | 用于存储页面的自定义数据 |
dir | 设置元素中内容的文本方向。 |
draggable New | 指定某个元素是否可以拖动 |
dropzone New | 指定是否将数据复制,移动,或链接,或删除 |
hidden New | hidden 属性规定对元素进行隐藏。 |
id | 规定元素的唯一 id |
lang | 设置元素中内容的语言代码。 |
spellcheck New | 检测元素是否拼写错误 |
style | 规定元素的行内样式(inline style) |
tabindex | 设置元素的 Tab 键控制次序。 |
title | 规定元素的额外信息(可在工具提示中显示) |
translate New | 指定是否一个元素的值在页面载入时是否需要翻译 |
HTMLElement.dataset
HTMLElement
接口的只读属性 dataset
提供了对元素上自定义数据属性(data-*
)读/写访问。它暴露了一个字符串映射(DOMStringMap
),其中包含每个 data-*
属性条目。
备注:
dataset
属性本身可以被读取,但是不能直接写入。相反,所有写入都必须是写入 dataset
的单个属性,而 dataset
又表示这些数据的属性。
Canvas
loadeddata
loadeddata
事件在媒体当前播放位置的视频帧(通常是第一帧)加载完成后触发。
备注
若在移动/平板设备
的浏览器设置中开启了流量节省(data-saver)
模式,该事件则不会被触发。
示例
使用addEventListener()
const video = document.querySelector('video')
video.addEventListener('loadeddata', (event) => {
console.log(
'Yay! readyState just increased to ' +
'HAVE_CURRENT_DATA or greater for first time.'
)
})
使用 onloadeddata
事件处理器属性
const video = document.querySelector('video')
video.onloadeddata = (event) => {
console.log(
'Yay! readyState just increased to ' +
'HAVE_CURRENT_DATA or greater for first time.',
)
}
loadedmetadata
loadedmetadata
事件在元数据(metadata
)被加载完成后触发。
语法
element.onloadedmetadata = handlerFunction
var handlerFunction = element.onloadedmetadata
Element.children
Element.children
是一个只读属性,返回 一个 Node
的子elements
,是一个动态更新的 HTMLCollection
。
语法
var children = node.children
备注
children
属性为只读属性,对象类型为 HTMLCollection
,你可以使用 elementNodeReference.children[1].nodeName
来获取某个子元素的标签名称。
例子
// parg 是一个指向<p>元素的对象引用
if (parg.childElementCount) {
// 检查这个<p>元素是否有子元素
// 译者注:childElementCount 有兼容性问题
var children = parg.children;
for (var i = 0; i < children.length; i++) {
// 通过 children[i] 来获取每个子元素
// 注意:List 是一个 live 的 HTMLCollection 对象,在这里添加或删除 parg 的子元素节点,都会立即改变 List 的值。
}
}
// 获取含有指定类名的子元素
const video = Array.from(parent.value.children).find((element: any) => {
return element.className.includes('nertc-video-container')
})
console.log('video:', video)
Element.firstElementChild
Element.firstElementChild
只读属性返回元素的第一个子元素,如果没有子元素,则为 null
。
Element.firstElementChild
仅包含元素节点。要获取所有子节点(包括文本和注释节点等非元素节点),请使用 Node.firstChild
值
一个 Element
对象,或 null
。
Node.firstChild
Node.firstChild
只读属性返回树中节点的第一个子节点,如果节点是无子节点,则返回 null
。
语法
var childNode = node.firstChild
描述
如果有一个子节点,childNode
是节点的第一个子节点的引用,否则为 null
<textarea>
标签点击enter
键发送文本
<textarea @keydown="onKeyboard" />
function onKeyboard (e) {
if (e.key === 'Enter') {
e.preventDefault() // 消除enter键换行
console.log('enter e:', e)
}
}
谷歌浏览器使用iframe
预览pdf
隐藏工具栏
<iframe :src="`${pdf.url}#toolbar=0`" width="900" height="400" frameborder="0">
<p>您的浏览器不支持iframe标签。</p>
</iframe>
浏览器页面从输入url都发生了什么?
- 根据网址进行DNS解析,将域名解析为IP地址
- 客户端根据IP地址找到对应的服务器,通过 TCP三次握手,与服务器建立连接
- 客户端发起HTTP请求,请求对应资源,这个请求通常是一个html文件
- 服务器响应并返回相应数据,HTTP报文(如:HTML文件)
- 浏览器通过网络接收数据,处理 HTML 并构造 DOM树
- CSS解析器处理CSS样式并构建 CSSOM树(CSS对象模型树)
- 将解析创建的 DOM树 和 CSSOM树 合成一个渲染树( Rendering Tree)
- 根据渲染树,计算每个可见元素的布局,然后将其绘制到屏幕上(在某些情况下,可以将内容提升到它们自己的层并进行合成,通过在 GPU 而不是 CPU 上绘制屏幕的一部分来提高性能,从而释放主线程。)
- 最后,客户端与服务器进行TCP四次挥手断开连接,也可能复用连接
不会被显示的元素,如 <head>
元素及其子元素,以及任何带有 display: none
的节点,如用户代理样式表中的 script { display: none; }
,都不会包含在渲染树中,因为它们不会出现在渲染输出中。应用了 visibility: hidden
的节点会包含在渲染树中,因为它们会占用空间。
关键渲染路径
关键渲染路径是浏览器将 HTML,CSS 和 JavaScript 转换为屏幕上的像素所经历的步骤序列。优化关键渲染路径可提高渲染性能。关键渲染路径包含了 文档对象模型(DOM)
,CSS 对象模型 (CSSOM)
,渲染树
和布局
。
Web 性能包含了服务器请求和响应、加载、执行脚本、渲染、布局和绘制每个像素到屏幕上。
网页请求从 HTML 文件请求开始。服务器返回 HTML——响应头和数据。然后浏览器开始解析 HTML,转换收到的数据为 DOM 树。浏览器每次发现外部资源就初始化请求,无论是样式、脚本或者嵌入的图片引用。有时请求会阻塞,这意味着解析剩下的 HTML 会被终止直到重要的资源被处理。浏览器接着解析 HTML,发请求和构造 DOM 直到文件结尾,这时开始构造 CSS 对象模型。等到 DOM 和 CSSOM 完成之后,浏览器构造渲染树,计算所有可见内容的样式。一旦渲染树完成布局开始,定义所有渲染树元素的位置和大小。完成之后,页面被渲染完成,或者说是绘制到屏幕上。
用户看到页面分为两个阶段:
- 页面内容加载完成。对应DOMContentLoaded
- 页面资源完成。对应Load
整个关键渲染路径包括以下几个步骤:
- 解析HTML,生成DOM树(DOM)
- 解析CSS,生成CSSOM树(CSSOM)
- 将DOM树和CSSOM树 合成渲染树(Rendering Tree)
- 根据渲染树,计算每个可见元素的布局(Layout)
- 将各个元素绘制到屏幕上(Paint)