Skip to content

Note 2

tabindex & 让 div 具有 focusblur 事件

tabindex 全局属性 指示其元素是否可以聚焦,以及它是否/在何处参与顺序键盘导航(通常使用Tab键,因此得名)。 div设置样式时,可正常使用 :hover 设置悬浮样式,但无法使用 :focus 设置聚焦样式 <div> 本身没有 @blur@focus 事件,可以通过添加 tabindex 属性:

html
<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个元素默认支持聚焦:

  1. href 属性的 <a> 标签
  2. href 属性的 <link> 标签
  3. <button></button> 标签
  4. <input /> 标签 (排除带有 type="hidden" 属性的)
  5. <select></select> 标签
  6. <textarea></textarea> 标签

以上的元素默认都可以使用 Tab 键,以及 JS focus() 方法聚焦 例如:

js
document.querySelector('a').focus()

如何设置 div 元素的 focus 样式? 使用 CSS伪类 :focus-within

:focus-within 是一个 CSS 伪类 ,表示一个元素获得焦点 或 该元素的后代元素获得焦点。换句话说,元素自身或者它的某个后代匹配 :focus 伪类。

css
/* 当 <div> 的某个后代获得焦点时,匹配 <div> */
div:focus-within {
  background: cyan;
}

设置 tabindex 后,元素变为可聚焦状态,而当元素被聚焦时,浏览器会在元素周围显示一个蓝色的轮廓,这属于浏览器的默认行为,可通过在元素上添加以下 CSS 样式来隐藏:

css
div {
  outline: none;
}

HTML5 新属性

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()

js
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 事件处理器属性

js
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)被加载完成后触发。

语法

js
element.onloadedmetadata = handlerFunction
var handlerFunction = element.onloadedmetadata

Element.children

Element.children 是一个只读属性,返回 一个 Node子elements ,是一个动态更新的 HTMLCollection

语法

js
var children = node.children

备注

children 属性为只读属性,对象类型为 HTMLCollection,你可以使用 elementNodeReference.children[1].nodeName 来获取某个子元素的标签名称。

例子

js
// 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

语法

js
var childNode = node.firstChild

描述

如果有一个子节点,childNode 是节点的第一个子节点的引用,否则为 null

<textarea>标签点击enter键发送文本

html
<textarea @keydown="onKeyboard" />
js
function onKeyboard (e) {
  if (e.key === 'Enter') {
    e.preventDefault() // 消除enter键换行
    console.log('enter e:', e)
  }
}

谷歌浏览器使用iframe预览pdf隐藏工具栏

html
<iframe :src="`${pdf.url}#toolbar=0`" width="900" height="400" frameborder="0">
  <p>您的浏览器不支持iframe标签。</p>
</iframe>

浏览器页面从输入url都发生了什么?

  1. 根据网址进行DNS解析,将域名解析为IP地址
  2. 客户端根据IP地址找到对应的服务器,通过 TCP三次握手,与服务器建立连接
  3. 客户端发起HTTP请求,请求对应资源,这个请求通常是一个html文件
  4. 服务器响应并返回相应数据,HTTP报文(如:HTML文件)
  5. 浏览器通过网络接收数据,处理 HTML 并构造 DOM树
  6. CSS解析器处理CSS样式并构建 CSSOM树(CSS对象模型树)
  7. 将解析创建的 DOM树 和 CSSOM树 合成一个渲染树( Rendering Tree)
  8. 根据渲染树,计算每个可见元素的布局,然后将其绘制到屏幕上(在某些情况下,可以将内容提升到它们自己的层并进行合成,通过在 GPU 而不是 CPU 上绘制屏幕的一部分来提高性能,从而释放主线程。)
  9. 最后,客户端与服务器进行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

整个关键渲染路径包括以下几个步骤:

  1. 解析HTML,生成DOM树(DOM)
  2. 解析CSS,生成CSSOM树(CSSOM)
  3. 将DOM树和CSSOM树 合成渲染树(Rendering Tree)
  4. 根据渲染树,计算每个可见元素的布局(Layout)
  5. 将各个元素绘制到屏幕上(Paint)

Released under the MIT License.