专业编程基础技术教程

网站首页 > 基础教程 正文

10个打开了我新世界大门的 WebAPI(中)「实践」

ccvgpt 2024-08-09 11:53:47 基础教程 12 ℃


作者:刘小夕

10个打开了我新世界大门的 WebAPI(中)「实践」

转发链接:https://mp.weixin.qq.com/s/aEbqUt3zSnq8EjdBtkBcpw

目录

10个打开了我新世界大门的 WebAPI(上)「实践」

10个打开了我新世界大门的 WebAPI(中)「实践」

10个打开了我新世界大门的 WebAPI(下)「实践」

前言

原来我对这些 Web API 一无所知,打开了我新世界的大门,未来 Web 可以做到更多,早日一统江湖吧,吼吼吼。

虽然这些 API 很多目前还存在兼容性的问题,但是还是有必要了解一下的,文中的代码,我已经都测试过了。希望你看完之后能够有所收获。

5. Channel Messaging API

Channel Messaging API 允许两个不同的脚本运行在同一个文档的不同浏览器上下文(比如两个 iframe,或者文档主体和一个 iframe,或者两个 worker)来直接通讯,在每端使用一个端口(port)通过双向频道(channel)向彼此传递消息。。

首先创建一个 MessageChannel 实例:

new MessageChannel()

这将返回一个 MessagePort 对象(通讯信道)。

然后,就可以通过 MessagePort.port1 或 MessageChannel.port2 设置端口。

实例化 MessageChannel 的上下文将使用 MessagePort.port1,另一个上下文将使用 MessagePort.port2。然后,就可以使用 postMessage API 传递消息了。

每个浏览器上下文都使用 Message.onmessage 监听消息,并使用事件的 data 属性获取消息内容。

让我们看一个简单的示例,在这里我们可以使用 MessageChannel 该文档和iframe 之间发送文本。

译者注:这个demo,原文中代码有错误,译者对代码进行了修改,亲测可以正常运行

<body>
    <header>
        <h2>Web APIs<h2>
    </header>
    <div class="web-api-cnt">
        <div class="web-api-card">
            <div class="web-api-card-head"> Demo - MessageChannel </div>
            <div class="web-api-card-body">
                <div id="error" class="close"></div>
                <div id="displayMsg">
                </div>
                <div>
                    <input id="input" type="text" placeholder="Send message to iframe" />
                </div>
                <div>
                    <button onclick="sendMsg()">Send Msg</button>
                </div>
                <div>
                    <iframe id="iframe" src="./iframe.content.html"></iframe>
                </div>
            </div>
        </div>
    </div>
</body>
<script>
    try {
        var channel = new MessageChannel()
        var port1 = channel.port1
    } catch (e) {
        error.innerHTML = "MessageChannel API not supported in this device."
        error.classList.remove("close")
    }

    iframe.addEventListener("load", onLoad)

    function onLoad() {
        port1.onmessage = onMessage
        iframe.contentWindow.postMessage("load", '*', [channel.port2])
    }

    function onMessage(e) {
        const newHTML = "<div>" + e.data + "</div>"
        displayMsg.innerHTML = displayMsg.innerHTML + newHTML
    }

    function sendMsg() {
        port1.postMessage(input.value)
    }

</script>

注意 iframe 的标签,我们在上面加载了一个 iframe.content.html 文件。按钮和文本是我们键入文字并向 iframe 发送消息的地方。

const channel = new MessageChannel()
const port1 = channel.port1
iframe.addEventListener("load", onLoad)
function onLoad() {
    port1.onmessage = onMessage
    iframe.contentWindow.postMessage("load", '*', [channel.port2])
}

function onMessage(e) {
    const newHTML = "<div>" + e.data + "</div>"
    displayMsg.innerHTML = displayMsg.innerHTML + newHTML
}

function sendMsg() {
    port1.postMessage(input.value)
}

我们初始化了 MessageChannel 和 port1 。我们向 iframe 添加了 load 监听。在这里,我们在port1 注册了 onmessage 监听,然后使用 postMessageAPI 将消息发送到 iframe 。看到 port2 被向下发送到 iframe 。

让我们看一下 iframe 的 iframe.content.html:

<body>
    <div class="web-api-cnt">

        <div class="web-api-card">
            <div class="web-api-card-head">
                Running inside an <i>iframe</i>
            </div>
            <div class="web-api-card-body">
                <div id="iframeDisplayMsg">
                </div>
                <div>
                    <input placeholder="Type message.." id="iframeInput" />
                </div>

                <div>
                    <button onclick="sendMsgiframe()">Send Msg from <i>iframe</i></button>
                </div>

            </div>
        </div>

    </div>
</body>

<script>
    var port2
    window.addEventListener("message", function(e) {
        port2 = e.ports[0]
        port2.onmessage = onMessage
    })

    function onMessage(e) {
        const newHTML = "<div>"+e.data+"</div>"
        iframeDisplayMsg.innerHTML = iframeDisplayMsg.innerHTML + newHTML
    }

    function sendMsgiframe(){
        port2.postMessage(iframeInput.value)
    }
</script>

在这里,我们注册了一个消息事件处理函数。我们检索 port2 并在其上设置onmessage 事件处理函数。现在,我们可以从 iframe 接收消息并将其发送到其父文档。

try it: https://web-api-examples.github.io/channelmessaging.html

译者注:这个 try 不起来哈,可以拷贝我上面的代码在本地测试

6. Vibration API

大多数现代移动设备包括振动硬件,其允许软件代码通过使设备摇动来向用户提供物理反馈。Vibration API 为 Web 应用程序提供访问此硬件(如果存在)的功能,如果设备不支持此功能,则不会执行任何操作。

navigator.vibrate(pattern) 控制振动,pattern 是描述振动模式的单个数字或数字数组。

navigator.vibrate(200);
navigator.vibrate([200]);

以上两个例子都可以使设备振动 200?ms 并停止.

navigator.vibrate([200,300,400])

这将使设备振动200毫秒,暂停300毫秒,振动400毫秒,然后停止。

可以通过传递0,[],[0,0,0](全零数组)来停止振动。

我们看一个简单的演示:

<body>
    <header>
        <h2>Web APIs<h2>
    </header>
    <div class="web-api-cnt">

        <div class="web-api-card">
            <div class="web-api-card-head">
                Demo - Vibration
            </div>
            <div class="web-api-card-body">
                <div id="error" class="close"></div>
                <div>
                    <input id="vibTime" type="number" placeholder="Vibration time" />
                </div>

                <div>
                    <button onclick="vibrate()">Vibrate</button>
                </div>

            </div>
        </div>

    </div>
</body>

<script>
    if(navigator.vibrate) {
        function vibrate() {
            const time = vibTime.value
            if(time != "")
                navigator.vibrate(time)
        }
    } else {
        error.innerHTML = "Vibrate API not supported in this device."
        error.classList.remove("close")        
    }
</script>

我们有输入和一个按钮。在输入框中输入振动的持续时间,然后点击按钮。设备将在输入的时间内振动

try it: https://web-api-examples.github.io/vibration.html

译者注:在安卓手机上测试正常

7. Broadcast Channel API

Broadcast Channel API 允许相同源下的不同浏览上下文的消息或数据进行通信。浏览上下文可以是窗口、iframe 等。

BroadcastChannel 类用于创建或加入频道。

const politicsChannel = new BroadcastChannel("politics")

politics 将是频道的名称。任何通过 politics 来初始化 BroadcastChannel 构造函数的上下文都将加入频道,它将接收在该频道上发送的任何消息,并且可以将消息发送到该频道。

如果是第一个使用 BroadcastChannel 的构造函数,politics 则会创建该频道。

要发布到频道,请使用 BroadcastChannel.postMessageAPI

要订阅频道(收听消息),请使用该 BroadcastChannel.onmessage 事件。

为了演示广播频道的用法,我构建了一个简单的聊天应用程序:

<body>
    <header>
        <h2>Web APIs<h2>
    </header>
    <div class="web-api-cnt">
        <div class="web-api-card">
            <div class="web-api-card-head"> Demo - BroadcastChannel </div>
            <div class="web-api-card-body">
                <div class="page-info">Open this page in another <i>tab</i>, <i>window</i> or <i>iframe</i> to chat with
                    them.</div>
                <div id="error" class="close"></div>
                <div id="displayMsg" style="font-size:19px;text-align:left;">
                </div>
                <div class="chatArea">
                    <input id="input" type="text" placeholder="Type your message" />
                    <button onclick="sendMsg()">Send Msg to Channel</button>
                </div>
            </div>
        </div>
    </div>
</body>
<script>
    const l = console.log;
    try {
        var politicsChannel = new BroadcastChannel("politics")
        politicsChannel.onmessage = onMessage
        var userId = Date.now()
    } catch (e) {
        error.innerHTML = "BroadcastChannel API not supported in this device."
        error.classList.remove("close")
    }

    input.addEventListener("keydown", (e) => {
        if (e.keyCode === 13 && e.target.value.trim().length > 0) {
            sendMsg()
        }
    })

    function onMessage(e) {
        const { msg, id } = e.data
        const newHTML = "<div class='chat-msg'><span><i>" + id + "</i>: " + msg + "</span></div>"
        displayMsg.innerHTML = displayMsg.innerHTML + newHTML
        displayMsg.scrollTop = displayMsg.scrollHeight
    }

    function sendMsg() {
        politicsChannel.postMessage({ msg: input.value, id: userId })

        const newHTML = "<div class='chat-msg'><span><i>Me</i>: " + input.value + "</span></div>"
        displayMsg.innerHTML = displayMsg.innerHTML + newHTML

        input.value = ""

        displayMsg.scrollTop = displayMsg.scrollHeight
    }  
</script>

初始化了 politicsChannel ,并在 politicsChannel 上设置了一个 onmessage事件监听器,以便它可以接收和显示消息。

点击按钮时,会调用 sendMsg 函数。它通过 BroadcastChannel#postMessageAPI将消息发送到 politicsChannel。初始化相同脚本的 tab 页,iframe 或worker 都将接收从此处发送的消息,因此该页面可以接收其他上下文发送的消息。

Try it: https://web-api-examples.github.io/broadcastchannel.html

8. Payment Request API

Payment Request API 提供了为商品和服务选择支付途径的方法。

该 API 提供了一种一致的方式来向不同的商家提供付款细节,而无需用户再次输入细节。

它向商家提供账单地址,收货地址,卡详细信息等信息。

注意: 此 API 提供了用户付款明细,但并不会带来新的付款方式。

让我们看一个演示如何使用付款请求 API 接受信用卡付款的演示:

<body>
    <header>
        <h2>Web APIs<h2>
    </header>
    <div class="web-api-cnt">
        <div class="web-api-card">
            <div class="web-api-card-head"> Demo - Credit Card Payment </div>
            <div class="web-api-card-body">
                <div id="error" class="close"></div>
                <div>
                    <button onclick="buy()">Buy</button>
                </div>
            </div>
        </div>
    </div>
</body>
<script>
    const networks = ["visa", "amex"]
    const types = ["debit", "credit"]

    const supportedInstruments = [
        {
            supportedMethods: "basic-card",
            data: {
                supportedNetworks: networks,
                supportedTypes: types
            }
        }
    ]

    const details = {
        total: {
            label: "Total",
            amount: {
                currency: "USD",
                value: "100"
            }
        },
        displayItems: [
            {
                label: "Item 1",
                amount: {
                    currency: "USD",
                    value: "50"
                }
            },
            {
                label: "Item 2",
                amount: {
                    currency: "USD",
                    value: "50"
                }
            },
        ]
    }

    try {
        var paymentRequest = new PaymentRequest(supportedInstruments, details)
    } catch (e) {
        error.innerHTML = "PaymentRequest API not supported in this device."
        error.classList.remove("close")
    }

    function buy() {
        paymentRequest.show().then(response => {
            console.log(response)
        })
    }
</script>

networks,types 和 supportedTypes 都是描述付款方式。details 列出了我们的购买商品和总费用。

构建 PaymentRequest 实例,paymentRequest.show() 将在浏览器中显示付款界面。并在 Promise 成功的回调中处理用户的数据。

它们是使用 Payment API 进行付款的许多配置,至少通过上面的示例,我们已经了解了 Payment Request API 的使用方式和工作方式。

try it: https://web-api-examples.github.io/paymentrequest.html

译者注:测试了下,但是没有走完全流程,毕竟我坚决不付款的~

本篇未完结,请见下一篇

推荐JavaScript经典实例学习资料文章

「图文」ESLint 在中大型团队的应用实践

Deno是代码的浏览器,你认同吗?

前端存储除了 localStorage 还有啥?

Javascript 多线程编程?的前世今生

微前端方案 qiankun(实践及总结)

「图文」V8 垃圾回收原来这么简单?

Webpack 5模块联邦引发微前端的革命?

基于 Web 端的人脸识别身份验证「实践」

「前端进阶」高性能渲染十万条数据(时间分片)

「前端进阶」高性能渲染十万条数据(虚拟列表)

图解 Promise 实现原理(一):基础实现

图解 Promise 实现原理(二):Promise 链式调用

图解 Promise 实现原理(三):Promise 原型方法实现

图解 Promise 实现原理(四):Promise 静态方法实现

实践教你从零构建前端 Lint 工作流「干货」

高性能多级多选级联组件开发「JS篇」

深入浅出讲解Node.js CLI 工具最佳实战

延迟加载图像以提高Web网站性能的五种方法「实践」

比较 JavaScript 对象的四种方式「实践」

使用Service Worker让你的 Web 应用如虎添翼(上)「干货」

使用Service Worker让你的 Web 应用如虎添翼(中)「干货」

使用Service Worker让你的 Web 应用如虎添翼(下)「干货」

前端如何一次性处理10万条数据「进阶篇」

推荐三款正则可视化工具「JS篇」

如何让用户选择是否离开当前页面?「JS篇」

JavaScript开发人员更喜欢Deno的五大原因

仅用18行JavaScript实现一个倒数计时器

图文细说JavaScript 的运行机制

一个轻量级 JavaScript 全文搜索库,轻松实现站内离线搜索

推荐Web程序员常用的15个源代码编辑器

10个实用的JS技巧「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(一)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(二)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(三)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(四)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(五)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(六)「值得收藏」

深入JavaScript教你内存泄漏如何防范

手把手教你7个有趣的JavaScript 项目-上「附源码」

手把手教你7个有趣的JavaScript 项目-下「附源码」

JavaScript 使用 mediaDevices API 访问摄像头自拍

手把手教你前端代码如何做错误上报「JS篇」

一文让你彻底搞懂移动前端和Web 前端区别在哪里

63个JavaScript 正则大礼包「值得收藏」

提高你的 JavaScript 技能10 个问答题

JavaScript图表库的5个首选

一文彻底搞懂JavaScript 中Object.freeze与Object.seal的用法

可视化的 JS:动态图演示 - 事件循环 Event Loop的过程

教你如何用动态规划和贪心算法实现前端瀑布流布局「实践」

可视化的 js:动态图演示 Promises & Async/Await 的过程

原生JS封装拖动验证滑块你会吗?「实践」

如何实现高性能的在线 PDF 预览

细说使用字体库加密数据-仿58同城

Node.js要完了吗?

Pug 3.0.0正式发布,不再支持 Node.js 6/8

纯JS手写轮播图(代码逻辑清晰,通俗易懂)

JavaScript 20 年 中文版之创立标准

值得收藏的前端常用60余种工具方法「JS篇」

箭头函数和常规函数之间的 5 个区别

通过发布/订阅的设计模式搞懂 Node.js 核心模块 Events

「前端篇」不再为正则烦恼

「速围」Node.js V14.3.0 发布支持顶级 Await 和 REPL 增强功能

深入细品浏览器原理「流程图」

JavaScript 已进入第三个时代,未来将何去何从?

前端上传前预览文件 image、text、json、video、audio「实践」

深入细品 EventLoop 和浏览器渲染、帧动画、空闲回调的关系

推荐13个有用的JavaScript数组技巧「值得收藏」

前端必备基础知识:window.location 详解

不要再依赖CommonJS了

犀牛书作者:最该忘记的JavaScript特性

36个工作中常用的JavaScript函数片段「值得收藏」

Node + H5 实现大文件分片上传、断点续传

一文了解文件上传全过程(1.8w字深度解析)「前端进阶必备」

【实践总结】关于小程序挣脱枷锁实现批量上传

手把手教你前端的各种文件上传攻略和大文件断点续传

字节跳动面试官:请你实现一个大文件上传和断点续传

谈谈前端关于文件上传下载那些事【实践】

手把手教你如何编写一个前端图片压缩、方向纠正、预览、上传插件

最全的 JavaScript 模块化方案和工具

「前端进阶」JS中的内存管理

JavaScript正则深入以及10个非常有意思的正则实战

前端面试者经常忽视的一道JavaScript 面试题

一行JS代码实现一个简单的模板字符串替换「实践」

JS代码是如何被压缩的「前端高级进阶」

前端开发规范:命名规范、html规范、css规范、js规范

【规范篇】前端团队代码规范最佳实践

100个原生JavaScript代码片段知识点详细汇总【实践】

关于前端174道 JavaScript知识点汇总(一)

关于前端174道 JavaScript知识点汇总(二)

关于前端174道 JavaScript知识点汇总(三)

几个非常有意思的javascript知识点总结【实践】

都2020年了,你还不会JavaScript 装饰器?

JavaScript实现图片合成下载

70个JavaScript知识点详细总结(上)【实践】

70个JavaScript知识点详细总结(下)【实践】

开源了一个 JavaScript 版敏感词过滤库

送你 43 道 JavaScript 面试题

3个很棒的小众JavaScript库,你值得拥有

手把手教你深入巩固JavaScript知识体系【思维导图】

推荐7个很棒的JavaScript产品步骤引导库

Echa哥教你彻底弄懂 JavaScript 执行机制

一个合格的中级前端工程师需要掌握的 28 个 JavaScript 技巧

深入解析高频项目中运用到的知识点汇总【JS篇】

JavaScript 工具函数大全【新】

从JavaScript中看设计模式(总结)

身份证号码的正则表达式及验证详解(JavaScript,Regex)

浏览器中实现JavaScript计时器的4种创新方式

Three.js 动效方案

手把手教你常用的59个JS类方法

127个常用的JS代码片段,每段代码花30秒就能看懂-【上】

深入浅出讲解 js 深拷贝 vs 浅拷贝

手把手教你JS开发H5游戏【消灭星星】

深入浅出讲解JS中this/apply/call/bind巧妙用法【实践】

手把手教你全方位解读JS中this真正含义【实践】

书到用时方恨少,一大波JS开发工具函数来了

干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)

手把手教你JS 异步编程六种方案【实践】

让你减少加班的15条高效JS技巧知识点汇总【实践】

手把手教你JS开发H5游戏【黄金矿工】

手把手教你JS实现监控浏览器上下左右滚动

JS 经典实例知识点整理汇总【实践】

2.6万字JS干货分享,带你领略前端魅力【基础篇】

2.6万字JS干货分享,带你领略前端魅力【实践篇】

简单几步让你的 JS 写得更漂亮

恭喜你获得治疗JS this的详细药方

谈谈前端关于文件上传下载那些事【实践】

面试中教你绕过关于 JavaScript 作用域的 5 个坑

Jquery插件(常用的插件库)

【JS】如何防止重复发送ajax请求

JavaScript+Canvas实现自定义画板

Continuation 在 JS 中的应用「前端篇」

作者:刘小夕

转发链接:https://mp.weixin.qq.com/s/aEbqUt3zSnq8EjdBtkBcpw

最近发表
标签列表