最近將chrome更新到最新的版本,然後發現以前可以正常使用的功能無法使用了,經過分析後發現是瀏覽器新版本才出現的問題,今天記錄以下。
一、遇到的問題
我們具體的問題場景,在A頁面中需要開啟B頁面,同時需要在兩個頁面之間共享一些資料;
在A頁面中我們將共享的資料儲存到sessionStorage中,並新建超連結元素並觸發其單擊事件。
sessionStorage.setItem('parameter', JSON.stringify(parameter));
var link = angular.element('<a href="' + url + '" rel="noopener" target="' + target + '"></a>');
angular.element(document.body).append(link);
link[0].click();
link.remove();
然後在B頁面中獲取儲存在sessionStorage中的資料並進行處理。
var key = 'parameter';
var parameter = sessionStorage.getItem(key);
if (parameter) {
parameterObj = JSON.parse(para);
......
sessionStorage.removeItem(key);
}
但是將chrome瀏覽器更新到89.0.4389.90 之後,發現A頁面儲存的資料在B頁面中無法獲取到。
檢視chrome的更新說明,發現其針對sessionStorage進行了更新.
Stop cloning sessionStorage for windows opened with noopener
When a window is opened with noopener,
Chrome will no longer clone the sessionStorage of its opener;
it will instead start an empty sessionStorage namespace.
This brings Chrome in conformance with the HTML specification.
通過Chrome Plateform Status我們可以看到全平臺的89版本的Chrome預設開啟了這個功能,也可以看到其他幾個主流的瀏覽器對這個功能的支援情況。
https://www.chromestatus.com/feature/5679997870145536
When a window is opened with noopener, Chrome should not clone the sessionStorage of its opener; it should instead start from an empty sessionStorage namespace.
Motivation
This is a bugfix to match the HTML specification, which added this behavior in 2017: https://github.com/whatwg/html/pull/2832
Status in Chromium
Blink components: Blink>Storage
Enabled by default (tracking bug) in:
Chrome for desktop release 89
Chrome for Android release 89
Android WebView release 89
Consensus & Standardization
After a feature ships in Chrome, the values listed here are not guaranteed to be up to date.
Firefox:Shipped/Shipping
Edge:Positive
Safari:No signal
Web Developers:No signals
二、sessionStorage的規範
- 頁面會話在瀏覽器開啟期間一直保持,並且重新載入或恢復頁面仍會保持原來的頁面會話。
- 在新標籤或視窗開啟一個頁面時會複製頂級瀏覽會話的上下文作為新會話的上下文,這點和 session cookies 的執行方式不同。
- 開啟多個相同的URL的Tabs頁面,會建立各自的sessionStorage。
- 關閉對應瀏覽器視窗(Window)/ tab,會清除對應的sessionStorage。
三、解決方案
通過以上分析我們可以知道,新版本的Chrome瀏覽器不會再複製sessionStorage給通過noopener方式開啟的新頁面,導致無法在新的標籤頁裡邊訪問到共享的資料,由於開啟的是我們同一個站點的頁面,可以直接將超連結的rel的值改為opener即可。
sessionStorage.setItem('parameter', JSON.stringify(parameter));
var link = angular.element('<a href="' + url + '" rel="opener" target="' + target + '"></a>');
angular.element(document.body).append(link);
link[0].click();
link.remove();