前言
在本文中,将介绍一些鲜为人知但却十分有用的API,如:
Page Visibility API
Web Share API
Broadcast Channel API
Internationalization API
咱们将一起看看它们是什么,咱们应该在哪里应用它们,以及如何应用它们。
Page Visibility API
这是一个鲜为人知的 web API,在JS现状考察中,它的认知度排名倒数第四。它能够让你晓得用户何时来到了页面。精确地说,只有页面的可见性状态发生变化,无论是用户最小化、最大化窗口还是切换标签页,该API都会触发一个事件。
在过来,你不得不应用一些噱头来理解用户是否切换了标签页或最小化了窗口。最风行的形式是应用blur
和focus
浏览器事件。应用这些事件会导致相似上面状况的产生:
window.addEventListener("focus", function () { // User is back on the page // Do Something});window.addEventListener("blur", function () { // User left the page // Do Something});
后面的代码能够工作,然而不合乎预期。因为blur
事件是在页面失去焦点时触发的,所以当用户点击搜寻栏、alert
对话框、控制台或窗口边框时,它就会被触发。所以,blur
和focus
只通知咱们页面是否被激活,但不通知咱们页面的内容是否被暗藏或显示。
什么时候应用
一般来说,咱们想要应用Page Visibility API
,是心愿用来进行不必要的程序。比如说当用户没有看到页面时,或者执行后盾操作时。具体的场景能够是:
- 当用户来到页面时暂停视频、图像旋转或动画;
- 如果页面显示来自API的实时数据,在用户来到时临时进行实时显示的行为;
- 发送用户剖析报告。
如何应用
Page Visibility API
带来了两个属性和一个事件,用于拜访页面可见性状态:
document.hidden
:该属性是全局可见并且只读。尽量避免应用该属性,因为当初曾经被废除了。当拜访该属性时,如果页面是暗藏状态则返回true
,如果页面是可见状态则返回false
。document.visibilityState
:该属性是document.hidden
更新后的版本。当拜访该属性时,会依据页面的可见性状态返回四个可能的值:visible
:该页面是可见的,或者精确地说,它没有被最小化,也不在另一个标签页。hidden
:该页面不可见,它是最小化的,或者在另一个标签页。prerender
:这是一个可见页面在预渲染时的初始状态。一个页面的可见性状态能够从prerender
开始,而后扭转到另一个状态,但它不能从另一个状态扭转到prerender
。unloaded
:该页面正在从内存中卸载。
visibilitychange
:这是一个由document
对象提供的事件,当页面的visibilityState
发生变化时被触发。
document.addEventListener("visibilitychange", () => { if (document.visibilityState === "visible") { // page is visible } else { // page is hidden }});
为了理解如何应用Page Visibility API
,让咱们用该个性来实现当用户来到页面时,暂停视频以及进行从API获取资源。首先,我将应用vite.js
,它是一个疾速启动新我的项目的神奇工具:
npm create [email protected] unknown-web-apis
当被要求抉择一个框架时,抉择vanilla
来创立一个vanilla
javascript我的项目。实现之后,返回新文件夹,装置必要的npm
包并启动开发服务器:
cd unknown-web-apisnpm installnpm run dev
关上localhost:3000/,你将看到你的Vite我的项目启动和运行!
首先,咱们间接跳转到/main.js
文件并删除所有样板代码。其次,关上/index.html
,在id
为#app
的div
标签外部增加一个video
元素,下面能够增加你想增加的任意视频文件。这里我应用了一只正在跳舞的耀西。
<div id="app"> <video controls id="video"> <source src="./yoshi.mp4" /> </video></div>
回到/main.js
,咱们将向document
对象增加一个事件监听器,用来监听visibilitychange
事件。而后当页面显示或暗藏时,咱们能够拜访document.visibilityState
属性的值。
document.addEventListener("visibilitychange", () => { console.log(document.visibilityState);});
你能够返回页面的控制台,当最小化窗口或者切换到另一个标签页时,查看页面可见性状态。当初,在事件监听器外部,咱们能够查看document.visibilityState
属性,当属性值为hidden
时暂停视频,当属性值为visible
时播放视频。当然,咱们首先要应用document.querySelector()
抉择video
元素。
const video = document.querySelector("#video");document.addEventListener("visibilitychange", () => { if (document.visibilityState === "visible") { video.play(); } else { video.pause(); }});
当初,只有用户来到页面,视频就会进行。另一个应用Page Visibility API
的场景是,当用户没有查看页面时,进行获取不必要的资源。为了看成果,咱们将编写一个函数不间断地从quotable.io API获取随机援用,并当页面暗藏时暂停该行为。首先,咱们将在/index.html
创立一个新的div
标签来存储援用。
<div id="app"> <video controls id="video"> <source src="./yoshi.mp4" /> </video> <div id="quote"></div></div>
回到/main.js
,咱们应用Fetch API发动对quotable.io
端点https://api.quotable.io/random 的调用,而后将后果插入到quote
div中。
const quote = document.querySelector('#quote');const getQuote = async () => { try { const response = await fetch('<https://api.quotable.io/random>'); const { content, author, dateAdded } = await response.json(); const parsedQuote = ` <q>${content}</q> <br> <p>- ${author}</p><br> <p>Added on ${dateAdded}</p>`; quote.innerHTML = parsedQuote; } catch (error) { console.error(error); }};
让咱们简略地解释一下此处产生了什么。首先咱们从DOM中选中了quote
元素。而后申明getQuote
函数,该函数是一个异步函数,容许咱们应用await
关键字进行期待,直到从API中获取到数据。获取的数据是JSON格局的,因而咱们再次应用await
关键字来期待,直到数据被解析为JavaScript对象。
quotable.io
的API为咱们提供了content
、author
和dateAdded
等属性,咱们把这些属性注入并显示在quote
div中。这样做是没问题的,然而援用只会获取一次,因而咱们能够应用setInterval()
每10秒来调用一次函数。
const quote = document.querySelector('#quote');const getQuote = async () => { try { const response = await fetch('<https://api.quotable.io/random>'); const { content, author, dateAdded } = await response.json(); const parsedQuote = ` <q>${content}</q> <br> <p>- ${author}</p><br> <p>Added on ${dateAdded}</p>`; quote.innerHTML = parsedQuote; } catch (error) { console.error(error); }};getQuote();setInterval(getQuote, 10000);
如果用户最小化窗口或者切换标签页,该页面依然会获取援用,创立没有必要的网络加载。为了解决这个问题,在获取援用之前咱们能够查看以后页面是否可见。
const getQuote = async () => { if (document.visibilityState === 'visible') { try { const response = await fetch('<https://api.quotable.io/random>'); const { content, author, dateAdded } = await response.json(); const parsedQuote = ` <q>${content}</q> <br> <p>- ${author}</p><br> <p>Added on ${dateAdded}</p>`; quote.innerHTML = parsedQuote; } catch (error) { console.error(error); } }};getQuote();setInterval(getQuote, 10000);
当初,咱们只会在页面对用户可见的状况下获取援用。
兼容性
广泛支持
Web Share API
这是什么
Web Share API
也是最不为人所知的API之一,但却十分有用。它能够让你拜访操作系统的原生分享机制,这对挪动端用户特地有用。有了这个API,你能够分享文本、链接和文件,而不须要创立你本人的分享机制或应用第三方的分享机制。
什么时候应用
用处曾经不言自明。你能够用它将你的页面内容分享到社交媒体上,或将其复制到用户的剪贴板上。
如何应用
Web Share API
赋予咱们两个接口来拜访用户的分享零碎:
navigator.canShare()
:承受你想分享的数据作为参数,并依据其是否可分享,来返回一个布尔参数。navigator.share()
:返回一个promise
,如果分享胜利的话,该promise
将会resolve
。该接口会调用原生分享机制,并接管你想分享的数据作为参数。留神,它只能在用户按下链接或按钮时调用。也就是说,它须要transient activation(刹时激活)。分享数据是一个能够具备以下属性的对象:url
:要分享的链接text
:要分享的文本title
:要分享的题目files
:示意要分享的File
对象数组
为了理解如何应用该API,咱们将回收先前的用例,做一个选项应用Web Sharing API
来分享咱们的援用。首先,咱们必须在/index.html
新增一个分享按钮:
<div id="app"> <video controls id="video"> <source src="./yoshi.mp4" /> </video> <div id="quote"></div> <button type="button" id="share-button">Share Quote</button></div>
返回/main.js
从DOM中抉择分享按钮。而后,创立async
函数来分享想要分享的数据。
const shareButton = document.querySelector("#share-button");const shareQuote = async (shareData) => { try { await navigator.share(shareData); } catch (error) { console.error(error); }};
当初,咱们能够为shareButton
元素增加click
事件监听器,以此来调用shareQuote
函数。shareData.text
的值会是quote.textContent
属性,shareData.url
的值会是页面的URL,也就是location.href
属性。
const shareButton = document.querySelector("#share-button");const shareQuote = async (shareData) => { try { await navigator.share(shareData); } catch (error) { console.error(error); }};shareButton.addEventListener("click", () => { let shareData = { title: "A Beautiful Quote", text: quote.textContent, url: location.href, }; shareQuote(shareData);});
当初你能够通过你的原生操作系统与任何人分享你的援用。然而,须要留神的是,Web Share API
只有在上下文平安的状况下才会起作用,也就是说,页面是通过https://
或wss://
URLs提供的。
兼容性
根本不反对
Broadcast Channel API
这是什么
我想议论的另一个API是Broadcast Channel API
。它容许浏览器上下文相互发送和接管根本数据。浏览器上下文是指标签页、窗口、iframe
等元素,或任何能够显示页面的中央。出于平安考量,浏览器上下文之间的通信是不被容许的,除非它们是同源的并应用Broadcast Channel API
。对于两个同源的浏览器上下文,它们的URL必须有雷同的协定(如http/https
)、域(如example.com
)和端口(如:8080
)。
什么时候应用
Broadcast Channel API
通常用于在不同的标签页和窗口之间放弃页面状态同步,以进步用户体验或出于平安起因思考。它也能够用来晓得一个服务在另一个标签页或窗口中何时实现。应用场景有:
- 在所有标签页上登录或登记用户。
- 检测资源何时上传,并在所有页面中展现它。
- 批示
service worker
做一些幕后工作。
如何应用
Broadcast Channel API
波及一个BroadcastChannel
对象,该对象可用于向其余上下文发送信息。构造函数只有一个参数:作为标识符的字符串,该标识符从其余上下文连贯到频道。
const broadcast = new BroadcastChannel("new_channel");
一旦咱们在两个上下文中创立了具备雷同标识符的BroadcastChannel
对象,这个新的BroadcastChannel
对象将有两个可用的办法来开始进行通信:
BroadcastChannel.postMessage()
:在所有连贯的上下文中发送音讯。它承受任意类型的对象作为其惟一的参数,因而你能够发送各种各样的数据。broadcast.postMessage("Example message");
BroadcastChannel.close()
:敞开通道,向浏览器表明它不会再收到任何信息,这样它就能够把这些信息收集到垃圾回收中。
为了承受信息,BroadcastChannel
有一个message
事件,咱们能够应用addEventListener
或其onmessage
属性来监听。message
事件有一个data
属性,蕴含发送的数据和其余属性,以辨认发送音讯的上下文,如origin
、lastEventId
、source
和ports
。
broadcast.onmessage = ({data, origin}) => { console.log(`${origin} says ${data}`);};
让咱们看看如何通过应用先前的例子来应用Broadcast Channel API
。咱们的指标是制作另一个具备同源的浏览器上下文,并在两个上下文中展现雷同的援用。为了做到这一点,咱们将创立一个名为new-origin
的新文件夹,外面有一个新的/index.html
和/main.js
文件。
/new-origin/index.html
将是一个新的HTML模板,外面有一个#quote
div:
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="../favicon.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Vite App</title> </head> <body> <div id="quote"></div> <script type="module" src="./main.js"></script> </body></html>
在/new-origin/main.js
文件中,咱们将创立一个新的broadcast channel
,并从DOM中抉择#quote
元素:
const broadcast = new BroadcastChannel("quote_channel");const quote = document.querySelector("#quote");
在先前的/main.js
文件中,咱们将创立新的BroadcastChannel
对象,并连贯到"quote_channel"
。咱们还将批改getQuote
函数,将援用作为音讯发送到其余上下文。
const broadcast = new BroadcastChannel("quote_channel");//...const getQuote = async () => { try { const response = await fetch("<https://api.quotable.io/random>"); const {content, author, dateAdded} = await response.json(); const parsedQuote = ` <q>${content}</q> <br> <p>- ${author}</p><br> <p>Added on ${dateAdded}</p>`; quote.innerHTML = parsedQuote; broadcast.postMessage(parsedQuote); } catch (error) { console.error(error); }};
回到/new-origin/main.js
文件,咱们将监听message
事件并在每次发送新的援用时扭转quote.innerHTML
。
const broadcast = new BroadcastChannel("quote_channel");const quote = document.querySelector("#quote");broadcast.onmessage = ({data}) => { quote.innerHTML = data;};
当初你能够看到http://localhost:3000/new-origin/
中的援用是如何变动为http://localhost:3000
中的援用的。你也能够留神到,当http://localhost:3000
标签被暗藏时,援用并没有扭转,因为它只在其页面可见性状态为可见时才会去获取援用。
兼容性
广泛支持
Internationalization API
这是什么
在开发一个网页或应用程序时,须要将其内容翻译成其余语言以笼罩更宽泛的受众是十分常见的。然而,仅仅将你的网页文本翻译成你所须要的任何语言,并不足以使你的内容对讲该语言的人可用,因为像日期、数字、单位等货色在不同国家是不同的,可能会给你的用户带来困惑。
咱们假如你想在你的网页上展现日期"2022年11月8日",就像"11/8/22"。依据读者所在的国家,这些数据能够用三种不同的形式来浏览:
- "11/8/2022"或美国用户的MM/DD/YY。
- "8/11/2022"或欧洲和拉美用户的DD/MM/YY。
- "2011/8/22"或日本、中国和加拿大用户的YY/MM/DD。
这就是Internationalization API
(或I18n API
)来解决不同语言和地区的格局问题的中央。I18n API
是一个了不起的工具,有多种用处,但咱们不会深入研究,免得使本文过于简单。
如何应用
I18n API
应用locale
标识符来起作用。locale
标识符是一个字符串,用来示意用户的语言、城市、地区、方言以及其余偏好。精确的说,locale
标识符是一个字符串,由连字符分隔的子标签组成。子标签代表了用户偏好,比方语言、国家、地区或文字,并以以下形式格式化:
"zh"
:中文(语言);"zh-Hant"
:用繁体字(文字)书写的中文(语言);"zh-Hant-TW"
:在台湾(地区)应用的繁体字(文字)书写的中文(语言)。
还有更多的子标签来解决更多用户的偏好(如果你想理解更多,你能够查看RFC对语言标签的定义),但简而言之,I18n API
应用这些locale
标识符来晓得如何格式化所有语言敏感的数据。
更确切地说,I18n API
提供了一个Intl
对象,它带来了一堆专门的构造函数来解决对语言敏感的数据。在我看来,一些对国际化最有用的Intl
构造函数是:
Intl.DateTimeFormat()
:用于格式化日期和工夫。Intl.DisplayNames()
:用于格式化语言、地区和文字显示名字。Intl.Locale()
:用于构建和操作locale
标识符标签。Intl.NumberFormat()
:用于格式化数字。Intl.RelativeTimeFormat()
:用于格式化绝对工夫形容。
在咱们的例子中,咱们将重点关注Intl.DateTimeFormat()
构造函数,以依据用户的区域设置来格式化援用的dateAdded
属性。Intl.DateTimeFormat()
构造函数接管两个参数:定义日期格局约定的locale
字符串和用于自定义日期格局的options
对象。
创立的Intl.DateTimeFormat()
对象有一个format()
办法,它接管两个参数:咱们要格式化的Date
对象和用于自定义如何显示格式化日期的options
对象。
const logDate = (locale) => { const newDate = new Date("2022-10-24"); // YY/MM/DD const dateTime = new Intl.DateTimeFormat(locale, {timeZone: "UTC"}); const formatedDate = dateTime.format(newDate); console.log(formatedDate);};logDate("en-US"); // 10/24/2022logDate("de-DE"); // 24.10.2022logDate("zh-TW"); // 2022/10/24
留神:在Intl.DateTimeFormat
构造函数的options
参数中,咱们将timeZone
属性设置为"UTC"
,这样日期就不会被格式化为用户的当地工夫。在我的例子中,没有timeZone
的选项,日期被解析为 "10/23/2022"。
正如你所看到的,dateTime.format()
依据locale
的日期格局约定扭转日期。咱们能够应用navigator.language
全局属性在援用的日期上实现这一行为,该全局属性具备用户的首选locale
设置。为此,咱们将创立一个新的函数,接管一个日期字符串(YYYY-MM-DD格局),并依据用户的locale
返回格式化的日期。
const formatDate = (dateString) => { const date = new Date(dateString); const locale = navigator.language; const dateTimeFormat = new Intl.DateTimeFormat(locale, {timeZone: "UTC"}); return dateTimeFormat.format(date);};
咱们能够在getQuote()
函数中增加这个函数来解析dateAdded
日期。
const getQuote = async () => { if (document.visibilityState === "visible") { try { const response = await fetch("<https://api.quotable.io/random>"); const {content, author, dateAdded} = await response.json(); const parsedQuote = ` <q>${content}</q> <br> <p>- ${author}</p><br> <p>Added on ${formatDate(dateAdded)}</p>`; quote.innerHTML = parsedQuote; broadcast.postMessage(parsedQuote); } catch (error) { console.error(error); } }};
有了这个,咱们的援用就被本地化为用户的首选语言了!在我的例子中,我的navigator.language
值是"en"
,所以我的日期被格式化为MM/DD/YY。
兼容性
广泛支持
总结
读完这篇文章后,你当初能够灵便地理解这些API的存在以及如何应用它们。只管它们在JS现状考察中的认知度排名最初,但它们十分有用,晓得如何应用它们必定会进步你的开发教训。这些弱小的API并不为人所知,这意味着还有一些你我都不晓得的有用的API,所以当初是摸索并找到那个能够简化你的代码,并为你节俭大量开发工夫的API的最佳时机。
以上就是本文的所有内容,如有对你有所帮忙,欢送点赞珍藏转发~