前端新特性
文章目录
- css特性
- accent-color修改表单颜色
- aspect-ratio宽高比
- size-adjust调整字体大小,让不同字体获得一致的表现
- @layer控制层级权重
- css优化
- contain优化回流重绘(页面渲染)
- content-visibility按需渲染
- web特性
- dialog原生组件对话框
- datetime-local原生日期组件
- WebAuthn浏览器上进行认证的 API
- Top level await
- SharedArrayBuffer
- web优化
- Back/forward cache页面缓存
- loading="lazy"懒加载
- fetchpriority资源优先级控制
- structuredClone原生深拷贝
css特性
accent-color修改表单颜色
- 新增CSS属性accent-color,用于修改表单元素的颜色
- 表单元素例如 等,它们的样式是由用户代理样式表(user agent stylesheet)决定的,各自浏览器的实现都不一样。
::root {
accent-color: deeppink;
}
aspect-ratio宽高比
- 值得注意的是aspect-ratio的优先级比较低。当aspect-ratio和其他属性例如width height 、min-width 、min-height产生了冲突的话,会以后者为准。
.container img {
width: 100%;
aspect-ratio: 16 / 9;
}
size-adjust调整字体大小,让不同字体获得一致的表现
@font-face {
font-family: "Size Adjusted Arial";
src: local(Arial);
size-adjust: 150%;
}
@layer控制层级权重
- 未使用层的样式优先级高于使用了层的样式
- 层的声明顺序代表了层的优先级。越后声明的层优先级越高
@layer layer_name {
h1 {
color: blue;
}
}
//创建匿名层
@layer {
h1 {
color: blue;
}
}
//先声明再定义
@layer base;
@layer base {
...
}
//一次性声明多个层
@layer theme, layout, utilities;
//@import导入文件时创建层
@import './theme.css' layer(theme);
- 示例
/* 预先建立层顺序,从最低到最高优先级 */
@layer reset, theme, components, utilities;
/* 重置 */
@layer reset {}
/* 主题样式 */
@layer theme {}
/* 组件样式 */
@layer components {}
/* 功能样式 */
@layer utilities {}
//===其他文件使用==================================================
/* 预先定义层的顺序 */
@layer base,
theme,
layouts,
components,
utilities;
/* Base */
@import '../styles/base/normalize.css' layer(base); /* normalize or rest file */
@import '../styles/base/base.css' layer(base); /* body and base styles */
@import '../styles/base/theme.css' layer(theme); /* theme variables */
@import '../styles/base/typography.css' layer(theme); /* theme typography */
@import '../styles/base/utilities.css' layer(utilities); /* base utilities */
/* Layouts */
@import '../styles/components/post.css' layer(layouts); /* post layout */
/* Components */
@import '../styles/components/cards.css' layer(components); /* imports card */
@import '../styles/components/footer.css' layer(components); /* footer component */
css优化
contain优化回流重绘(页面渲染)
contain有如下值:
layout:该元素的内部布局与页面的其他部分完全隔离,内部不受外界任何东西的影响,同时也影响不了外部。
paint:内部元素的绘制不会超出该元素,超出的部分会不可见。
size:该元素的渲染不用去检测内部元素,即跟内部元素的尺寸无关。
style(不常用):设置 counters 和 quotes两个属性不会影响到外部。
还有另外两个值,是其他属性的组合:
content: layout + paint的结合
strict: layout + paint + size的结合
- 假如页面中有10000个元素,修改了最后一个元素的内容,如果你给每个元素加上 contain: strict属性,那么浏览器只需要重绘你修改的元素
content-visibility按需渲染
- 设置content-visibbily属性可以暂时跳过元素的渲染(包括布局和绘制),直到它需要被用到的时候再进行渲染。
- 通过这个属性,我们可以实现优先渲染首屏内容,页面其他部分先暂停渲染,这样可以极大地加速首屏展示时间,让用户更快体验到页面。
- 在离屏时只是不会渲染,但是可以通过DOM API或者网页搜索功能找到。
content-visibility:visible; 默认值,不产生影响,元素正常渲染。
content-visibility:hidden; 该元素内容会被跳过。
content-visibility:auto; 当元素不可见(且没有交互操作)时会跳过元素内容的渲染,需要的时候再渲染。
- 和其它隐藏样式的区别:
- display: none:DOM树中移除该元素,layout和paint都不参与。缺点是切换到展示状态时需要的代价较大。
- visibility: hidden:DOM树中保留该元素,且会参与layout,只是在图形绘制上隐藏。切换到展示状态需要的代价较低。但是由于该元素需要参与layout,内容变更时会影响到外部,所以总体页面的渲染耗时并没有减少。
- content-visibility: hidden:DOM树中保留该元素,不参与 layout和paint,页面渲染时会跳过该元素。但是它可以保留渲染状态,切换到展示状态时的代价很低。
web特性
dialog原生组件对话框
<dialog id="dialog">
<form method="dialog">
<p>Hi, I'm a dialog.</p>
<button>OK</button>
</form>
</dialog>
<button onclick="dialog.showModal()">Open Dialog</button>
- 默认元素是隐藏的,可以通过设置HTML属性open=true,或者使用 .show()和.showModal()来展示对话框内容。
- 如果元素里有表单元素并且设置了method=dialog,那么提交form表单时会关闭对话框并且把表单内容作为返回值。
datetime-local原生日期组件
<input type="datetime-local">
WebAuthn浏览器上进行认证的 API
- WebAuthn 采用的是非对称加密的认证方式,服务端储存的是公钥,对应的私钥由客户端保管。
- 用户不需要记忆密码,可以借助设备的生物认证传感器直接登录。
- 注册阶段
const publicKeyCredentialCreationOptions = {
challenge: Uint8Array.from(
randomStringFromServer, c => c.charCodeAt(0)),
rp: {
name: "Duo Security",
id: "duosecurity.com",
},
user: {
id: Uint8Array.from(
"UZSL85T9AFC", c => c.charCodeAt(0)),
name: "lee@webauthn.guide",
displayName: "Lee",
},
pubKeyCredParams: [{alg: -7, type: "public-key"}],
authenticatorSelection: {
authenticatorAttachment: "cross-platform",
},
timeout: 60000,
attestation: "direct"
};
const credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions
});
- 认证阶段
const publicKeyCredentialRequestOptions = {
challenge: Uint8Array.from(
randomStringFromServer, c => c.charCodeAt(0)),
allowCredentials: [{
id: Uint8Array.from(
credentialId, c => c.charCodeAt(0)),
type: 'public-key',
transports: ['usb', 'ble', 'nfc'],
}],
timeout: 60000,
}
const assertion = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions
});
Top level await
- 可以不使用async,直接在顶层使用await
- 但会存在一个坑:如果顶层文件使用了await,那么像DOMContentLoaded这种写在内部的生命周期可能会因为异步阻塞没有触发,并且很难找到是在其他文件顶层使用了Top level await
await Promise.resolve(console.log('🎉'));
SharedArrayBuffer
- SharedArrayBuffer即共享内存,可用于Web Worker和WebAssembly的场景。
- Web worker 与JS主线程的数据都是隔离的,通过postMessage()通信,传递的数据都需要被复制一份,数据量大时通信效率很低。SharedArrayBuffer允许 Worker 线程与主线程共享同一块内存。将数据写入SharedArrayBuffer后只需要传递内存地址即可。
- 使用WebAssembly时,wasm初始化时会向SharedArrayBuffer申请共享内存,通过传递指针的方式与JS进行数据交换
- 主线程
// 新建 1KB 共享内存
const sharedBuffer = new SharedArrayBuffer(1024);
// 主线程将共享内存的地址发送出去
w.postMessage(sharedBuffer);
// 在共享内存上建立视图,供写入数据
const sharedArray = new Int32Array(sharedBuffer);
- Worker 线程:
// Worker 线程
onmessage = function (ev) {
// 主线程共享的数据,就是 1KB 的共享内存
const sharedBuffer = ev.data;
// 在共享内存上建立视图,方便读写
const sharedArray = new Int32Array(sharedBuffer);
// ...
};
web优化
Back/forward cache页面缓存
- Chrome浏览器的一项优化。页面在离开时会先被缓存,浏览器前进或者后退操作时能直接使用。Firefox和Safari 也支持
- 在进入和离开页面时会触发事件pageshow和pagehide,并且加了persisted属性来区分是页面是否使用bfcache
loading="lazy"懒加载
- <img>和<iframe>都原生支持属性loading=“lazy”
<img src="image.png" loading="lazy" alt="…" width="200" height="200">
- eager :默认值。立刻加载资源;
- lazy:延迟加载,等元素即将出现在视窗时再加载
fetchpriority资源优先级控制
优先级提示是对现有浏览器资源加载优先级的补充。浏览器计算资源的优先级时会考虑这些因素:
- 资源类型,比如 CSS、Font、Scripts、Images等等不同类型资源具有不同的优先级。
- 引用资源的代码顺序。
- 使用preload标签属性。
- 使用async和defer标签属性。
当以上因素对资源优先级控制的精细度不够时,就需要用到Priority Hints。Priority Hints可以认为是在同等优先级的基础上进行调整。
- fetchpriority属性可以用在link, img, script, and iframe 标签上
- high:希望浏览器提高该资源的优先级。low:希望浏览器降低该资源的优先级。auto(默认):由浏览器自己决定优先级。
- Fetch API priority也可以传入上述三个选择值
<script>
fetch('https://example.com/', {priority: 'low'})
.then(data => {
// Trigger a low priority fetch
});
</script>
structuredClone原生深拷贝
- 对于引用类型的值,拷贝方式分为浅拷贝和深拷贝,浅拷贝就是只复制了对象的外层属性,通常用扩展运算符进行操作:
- 不能拷贝函数;
- 不能拷贝DOM nodes;
- 拷贝对象时会丢弃以下内容:
- RegExp 对象的
lastIndex
属性; - 属性的descriptors(描述),例如getters、setters、readable等;
- 原型链不会被拷贝,新对象的prototype都会指向Object;
- RegExp 对象的
const myDeepCopy = structuredClone(myOriginal);