sessonStorage
属性是允许前端访问和存储值的一个对象,和localStorage
一样使用,只是它们的生命周期有所不同,所以我要明确的了解sessionStorage
的会话周期边界情况,去避免一些使用引起的bug。
1、正常的我们的理解,sessionStorage
会在我们打开浏览器访问网页一直保持,刷新重新加载页面数据都会保持着,直到关闭该标签页
html
<html>
<body>
<h1>Hello, World!</h1>
<p>This is a test page A.</p>
<!-- 点击跳转到B -->
<a href="B.html">Go to test page B</a>
<script>
console.log("Hello from test page A!");
// 存储一个session
sessionStorage.setItem("message", "Hello from test page A!");
</script>
</body>
</html>
html
<html>
<body>
<h1>Hello, World!</h1>
<p>This is a test page B.</p>
<script>
console.log("Hello from test page B!");
console.log(sessionStorage)
</script>
</body>
</html>
由A存储的session值,点击跳转到B后,B仍能访问到
2、换一种方式,如果是使用_blank
打开新标签页呢?很尴尬,访问不到值了
html
<html>
<body>
<h1>Hello, World!</h1>
<p>This is a test page A.</p>
<!-- 点击跳转到新标签页B -->
<a target="_blank" href="B.html">Go to test page B</a>
<script>
console.log("Hello from test page A!");
// 存储一个session
sessionStorage.setItem("message", "Hello from test page A!");
</script>
</body>
</html>
- 换种方式,通过js脚本
window.open
去打开新标签页,奇怪的发现,又可以访问到值了
html
<html>
<body>
<h1>Hello, World!</h1>
<p>This is a test page A.</p>
<!-- 脚本跳转 -->
<button onclick="go()">Go to test page B</button>
<script>
console.log("Hello from test page A!");
// 存储一个session
sessionStorage.setItem("message", "Hello from test page A!");
function go() {
window.open('/B.html')
}
</script>
</body>
</html>
思考为何a标签跳转打开不行呢??
网上搜索看看了,原来a标签默认rel="noopener"
,这种情况下不携带sessionStorage
的值,需要配置rel="opener"
html
<html>
<body>
<h1>Hello, World!</h1>
<p>This is a test page A.</p>
<!-- 点击跳转到B -->
<a target="_blank" href="B.html" rel="opener">Go to test page B</a>
<script>
console.log("Hello from test page A!");
// 存储一个session
sessionStorage.setItem("message", "Hello from test page A!");
</script>
</body>
</html>
3、 换种方式,直接复制A页的访问连接,新建一个标签页打开,还是很尴尬,依旧访问不到值了
4、 再换种方式,将A页再新窗口打开,这时只是指标签页的移动,值能够访问到
综上情况看,我们需要注意了,会话不是在关闭浏览器前一直保留,而是标签页关闭就会销毁,有很多伙伴包括我刚开始接触前端都认为session在浏览器关闭前一直存储着,这就是边界理解错了,很可能在开发的时候写出bug,而且还需要主要新打开的标签页,通过代码打开的可以访问到,但是要注意a标签和window.open的不同,而人为打开的新标签无非共享访问
讲讲我为啥会遇到这样的误解,很早之前做后端的时候用于存储登录记录,后台有个session
,记得前辈说关闭浏览器就会失效,我也就一知半解没深究,后面就与前端的sessionStorage
搞混了,这两个并不是一个东西,后台存储的session
有个sessionId
,这个是存储在cookie
中的,请求时会带着,后台根据sessionId
去session
取值,判断是否登录,而通过对cookie
的过期时间配置就可以达到浏览器关闭cookie
销毁,从而session
失效。
最后
思考我们该如何处理人为打开新标签页呢???
其实呢,比如详情页,这些打开新标签页都应该根据接口响应获取数据,而不是通过sessionStorage
存储从别的地方带进详情页
不过就问题处理问题吧,前端该怎么尽量改进优化呢?我这里讲讲我的想法,通过SharedWorker
来处理
js
// worker.js
const set = new Set()
onconnect = event => {
const port = event.ports[0]
set.add(port)
// 接收信息
port.onmessage = e => {
// 广播信息
set.forEach(p => {
p.postMessage(e.data)
})
}
}
html
<html>
<body>
<h1>Hello, World!</h1>
<p>This is a test page A.</p>
<!-- 点击跳转到B -->
<a target="_blank" href="B.html">Go to test page B</a>
<button onclick="go()">Go to test page B</button>
<script>
console.log("Hello from test page A!");
// 存储一个session
sessionStorage.setItem("message", "Hello from test page A!");
function go() {
window.open("/B.html")
}
var worker = new SharedWorker("./worker.js")
worker.port.onmessage = function(e) {
var result = JSON.parse(e.data);
if (result.from === "B" && result.type === "init") {
worker.port.postMessage(JSON.stringify({ from: "A", type: "sessionStorage", sessionStorage: sessionStorage }));
}
}
</script>
</body>
</html>
html
<html>
<body>
<h1>Hello, World!</h1>
<p>This is a test page B.</p>
<script>
console.log("Hello from test page B!");
console.log(sessionStorage)
var worker = new SharedWorker("./worker.js")
worker.port.onmessage = function(e) {
var result = JSON.parse(e.data);
console.log(result.sessionStorage)
if (result.from === "A" && result.type === "sessionStorage") {
for (var key in result.sessionStorage) {
sessionStorage.setItem(key, result.sessionStorage[key]);
}
}
}
worker.port.postMessage(JSON.stringify({
type: "init",
from: "B"
}))
</script>
</body>
</html>