作者:刘小夕
转发链接:https://mp.weixin.qq.com/s/aEbqUt3zSnq8EjdBtkBcpw
目录
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经典实例学习资料文章
《图解 Promise 实现原理(二):Promise 链式调用》
《图解 Promise 实现原理(三):Promise 原型方法实现》
《图解 Promise 实现原理(四):Promise 静态方法实现》
《使用Service Worker让你的 Web 应用如虎添翼(上)「干货」》
《使用Service Worker让你的 Web 应用如虎添翼(中)「干货」》
《使用Service Worker让你的 Web 应用如虎添翼(下)「干货」》
《一个轻量级 JavaScript 全文搜索库,轻松实现站内离线搜索》
《细品269个JavaScript小函数,让你少加班熬夜(一)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(二)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(三)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(四)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(五)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(六)「值得收藏」》
《手把手教你7个有趣的JavaScript 项目-上「附源码」》
《手把手教你7个有趣的JavaScript 项目-下「附源码」》
《JavaScript 使用 mediaDevices API 访问摄像头自拍》
《一文彻底搞懂JavaScript 中Object.freeze与Object.seal的用法》
《可视化的 JS:动态图演示 - 事件循环 Event Loop的过程》
《可视化的 js:动态图演示 Promises & Async/Await 的过程》
《Pug 3.0.0正式发布,不再支持 Node.js 6/8》
《通过发布/订阅的设计模式搞懂 Node.js 核心模块 Events》
《「速围」Node.js V14.3.0 发布支持顶级 Await 和 REPL 增强功能》
《JavaScript 已进入第三个时代,未来将何去何从?》
《前端上传前预览文件 image、text、json、video、audio「实践」》
《深入细品 EventLoop 和浏览器渲染、帧动画、空闲回调的关系》
《推荐13个有用的JavaScript数组技巧「值得收藏」》
《36个工作中常用的JavaScript函数片段「值得收藏」》
《一文了解文件上传全过程(1.8w字深度解析)「前端进阶必备」》
《手把手教你如何编写一个前端图片压缩、方向纠正、预览、上传插件》
《JavaScript正则深入以及10个非常有意思的正则实战》
《前端开发规范:命名规范、html规范、css规范、js规范》
《100个原生JavaScript代码片段知识点详细汇总【实践】》
《手把手教你深入巩固JavaScript知识体系【思维导图】》
《一个合格的中级前端工程师需要掌握的 28 个 JavaScript 技巧》
《身份证号码的正则表达式及验证详解(JavaScript,Regex)》
《127个常用的JS代码片段,每段代码花30秒就能看懂-【上】》
《深入浅出讲解JS中this/apply/call/bind巧妙用法【实践】》
《干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)》
《面试中教你绕过关于 JavaScript 作用域的 5 个坑》
作者:刘小夕
转发链接:https://mp.weixin.qq.com/s/aEbqUt3zSnq8EjdBtkBcpw