问题一: 从页面 A 打开一个新页面 B,B 页面关闭(包括意外崩溃),如何通知 A?
首先,这个题目是前端通信题目,可以从3个方面来解答这个问题
- A 页面打开 B 页面,A、B 页面通信方式?
- B 页面正常关闭,如何通知 A 页面?
- B 页面意外崩溃,又该如何通知 A 页面?
首先,我们来看 A 页面打开 B 页面,A、B 页面通信方式:
A、B 页面通信方式有:
- url 传参
- postmessage
- localStorage
- WebSocket
- SharedWorker
- Service Worker
url 传参
A:
<!-- A.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>A</title>
</head>
<body>
<h1>A 页面</h1>
<button type="button" onclick="openB()">B</button>
<script>
window.name = 'A' //表示页面的名称
function openB() {
window.open("B.html", "B") // 第一个参数表示页面的名称
}
window.addEventListener('hashchange', function () {// 监听 hash
alert(window.location.hash)
}, false);
</script>
</body>
</html>
B:
<!-- B.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>B</title>
<button type="button" onclick="sendA()">发送A页面消息</button>
</head>
<body>
<h1>B 页面</h1>
<span></span>
<script>
window.name = 'B'
window.onbeforeunload = function (e) {
window.open('A.html#close', "A")
return '确定离开此页吗?';
}
</script>
</body>
</html>
总结: 上述知识点,首先A页面有一个Button点击事件,里面的方法window.open去往B页面,同时在B页面当中有一个onbeforeunload在浏览器关闭的时候触发,里面有一个window.open去往A页面,这就是A页面和B页面的一个通信方式,桥接它们的是A页面当中的hashchange事件,通过这个事件就可以接收到B页面传递过来的值.
postMessage
postMessage 是 h5 引入的 API,postMessage() 方法允许来自不同源的脚本采用异步方式进行有效的通信,可以实现跨文本文档、多窗口、跨域消息传递,可在多用于窗口间数据通信,这也使它成为跨域通信的一种有效的解决方案,简直不要太好用
A:
<!-- A.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>A</title>
</head>
<body>
<h1>A 页面</h1>
<button type="button" onclick="openB()">B</button>
<script>
window.name = 'A'
function openB() {
window.open("B.html?code=123", "B")
}
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
console.log('收到消息:', event.data)
}
</script>
</body>
</html>
B:
<!-- B.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>B</title>
<button type="button" onclick="sendA()">发送A页面消息</button>
</head>
<body>
<h1>B 页面</h1>
<span></span>
<script>
window.name = 'B'
function sendA() {
let targetWindow = window.opener // window.opener表示打开窗口A
targetWindow.postMessage('Hello A', "http://localhost:3000");
}
</script>
</body>
</html>
总结: postMessage通信的步骤是点击A页面的按钮跳转到B页面,在A页面通过监听message事件,接收B页面传递过来的数据event.data,在B页面点击按钮发送到A页面,将数据'hello A',传递到A页面,注意浏览的同源策略!
LocalStorage
// A
localStorage.setItem('testB', 'sisterAn');
// B
let testB = localStorage.getItem('testB');
console.log(testB)
总结: Localstorage本地存储用的场景很多也比较简单,但是要注意localStorage 仅允许你访问一个Document 源(origin)的对象 Storage;存储的数据将保存在浏览器会话中。如果 A 打开的 B 页面和 A 是不同源,则无法访问同一 Storage
接着,我们来看第二个问题,B 页面正常关闭,如何通知 A 页面?
首先在B页面监听window.onbeforeunload,然后再去执行window.onunload,我们可以通过这两个方法向A页面通信.
最后一个问题,B 页面意外崩溃,又该如何通知 A 页面?
我们可以利用 window 对象的 load 和 beforeunload 事件,通过心跳监控来获取 B 页面的崩溃,具体代码如下:
window.addEventListener('load', function () {
sessionStorage.setItem('good_exit', 'pending');
setInterval(function () {
sessionStorage.setItem('time_before_crash', new Date().toString());
}, 1000);
});
window.addEventListener('beforeunload', function () {
sessionStorage.setItem('good_exit', 'true');
});
if(sessionStorage.getItem('good_exit') &&
sessionStorage.getItem('good_exit') !== 'true') {
/*
insert crash logging code here
*/
alert('Hey, welcome back from your crash, looks like you crashed on: ' + sessionStorage.getItem('time_before_crash'));
}
总结: 首先,在页面加载的时候,监听load事件设置一个sessionStorage,设置它的键和状态"pedding"并且每隔一秒钟再设置一次,并且在页面关闭的时候触发beforeunload事件,并把它的值改为"true",接下来就判断pedding是否为"true".