专栏名称: 程序员大咖
程序员大咖,努力成就期待着的自己。分享程序员技术文章、程序员工具资源、程序员精选课程、程序员视频教程、程序员热点资讯、程序员学习资料等。
目录
相关文章推荐
手游那点事  ·  春节期间,10家游戏公司宣布了裁员 ·  4 天前  
手游那点事  ·  今天,率土团队单机新作公开Steam页面 ·  3 天前  
51好读  ›  专栏  ›  程序员大咖

几个你不知道却非常实用的JavaScript APIs

程序员大咖  · 公众号  ·  · 2025-01-19 10:24

正文

在本文中,将介绍一些鲜为人知但却非常有用的API,如:

  • Page Visibility API
  • Web Share API
  • Broadcast Channel API
  • Internationalization API

我们将一起看看它们是什么,我们应该在哪里使用它们,以及如何使用它们。

Page Visibility API

这是一个鲜为人知的 web API,在 JS现状调查 [1] 中,它的认知度排名倒数第四。它可以让你知道用户何时离开了页面。准确地说,只要页面的可见性状态发生变化,无论是用户最小化、最大化窗口还是切换标签页,该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 vite@latest unknown-web-apis

当被要求选择一个框架时,选择 vanilla 来创建一个 vanilla javascript项目。完成之后,前往新文件夹,安装必要的 npm 包并启动开发服务器:

cd unknown-web-apis
npm install
npm run dev

打开 localhost:3000/ [2] ,你将看到你的Vite项目启动和运行!

vite-new-project.png

首先,我们直接跳转到 /main.js 文件并删除所有样板代码。其次,打开 /index.html ,在 id #app div 标签内部添加一个 video 元素,上面可以添加你想添加的任意视频文件。这里我使用了一只正在跳舞的耀西。

<div id="app">
    <video controls id="video">
        <source src="./yoshi.mp4" />
    video>
div>
dancing-Yoshi.png

回到 /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 [3] 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 [4] 发起对 quotable.io 端点 https://api.quotable.io/random [5] 的调用,然后将结果插入到 quote div中。

const quote = document.querySelector('#quote');

const getQuote = async () => {
  try {
    const response = await fetch('');
    const { content, author, dateAdded } = await response.json();
    const parsedQuote = ${content} 
 

${author}


 

Added on ${dateAdded}

`
;
    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('');
    const { content, author, dateAdded } = await response.json();
    const parsedQuote = ${content} 
 

${author}


 

Added on ${dateAdded}

`
;
    quote.innerHTML = parsedQuote;
  } catch (error) {
    console.error(error);
  }
};

getQuote();

setInterval(getQuote, 10000);

如果用户最小化窗口或者切换标签页,该页面仍然会获取引用,创建没有必要的网络加载。为了解决这个问题,在获取引用之前我们可以检查当前页面是否可见。

const getQuote = async () => {
  if (document.visibilityState === 'visible') {
    try {
      const response = await fetch('');
      const { content, author, dateAdded } = await response.json();
      const parsedQuote = `
          ${content} 
 
          

${author}


 
          

Added on ${dateAdded}

`
;
      quote.innerHTML = parsedQuote;
    } catch (error) {
      console.error(error);
    }
  }
};

getQuote();

setInterval(getQuote, 10000);

现在,我们只会在页面对用户可见的情况下获取引用。

兼容性

广泛支持 [6]

Web Share API

这是什么

Web Share API 也是最不为人所知的API之一,但却非常有用。它可以让你访问操作系统的原生分享机制,这对移动端用户特别有用。有了这个API,你可以分享文本、链接和文件,而不需要创建你自己的分享机制或使用第三方的分享机制。

什么时候使用

用途已经不言自明。你可以用它将你的页面内容分享到社交媒体上,或将其复制到用户的剪贴板上。

如何使用

Web Share API 赋予我们两个接口来访问用户的分享系统:

  1. navigator.canShare() :接受你想分享的数据作为参数,并根据其是否可分享,来返回一个布尔参数。

  2. navigator.share() :返回一个 promise ,如果分享成功的话,该 promise 将会 resolve 。该接口会调用原生分享机制,并接收你想分享的数据作为参数。注意,它只能在用户按下链接或按钮时调用。也就是说,它需要 transient activation [7] (瞬时激活)。分享数据是一个可以具有以下属性的对象:

  • 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 Quotebutton>
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提供的。

兼容性

基本不支持 [8]

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:

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 Apptitle>
    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("");
  const {content, author, dateAdded} = await response.json();
  const parsedQuote = ${content} 
 

${author}


 

Added on ${dateAdded}

`
;
  quote.innerHTML = parsedQuote;
  broadcast.postMessage(parsedQuote);
 } catch (error) {
  console.error(error);
 }
};

回到 /new-origin/main.js 文件,我们将监听 message 事件并在每次发送新的引用时改变 quote.innerHTML







请到「今天看啥」查看全文