我想出兩種方案,
1、服務器端返回文件的時候,設置響應頭,
cache-control:no-cache
貌似是這樣,告訴瀏覽器不要緩存;
2、前端控制,核心是,如何區分代碼里修改 url 導致的刷新和用戶的刷新,代碼:
<script> let presentTime = (new Date()).getTime(), hrefWithoutSearch = location.protocol + '//' + location.host + location.pathname; if (localStorage.getItem('previousHref') === null) { localStorage.setItem('previousHref', hrefWithoutSearch + "?v=" + presentTime); localStorage.setItem('previousAccessTime', presentTime); location.href = hrefWithoutSearch + "?v=" + presentTime; } else { let interval = presentTime - parseInt(localStorage.getItem('previousAccessTime'), 10); if (interval > 2000) { localStorage.setItem('previousAccessTime', presentTime); location.href = hrefWithoutSearch + "?v=" + presentTime; } } </script>
原理:
- 代碼修改 url 的刷新,不能繼續刷新,否則陷入死循環;
- 用戶的刷新要修改 url,返回新的頁面;
所以,onbeforeunload,onunload 都無法來區分,我想到的可以區分的就是,用戶的操作
- 鍵盤事件:F5,CTRL+R,地址欄回車,地址欄旁邊的刷新按鈕
- 鼠標事件: 右鍵刷新
我覺得比較困難,尤其是地址欄回車按鈕和地址欄旁的刷新;所以想了另外一個妥協的辦法:
頁面每次加載,都去 localStorage 里獲取上次加載的時間 previousAccessTime,和當前時間一減,得出 interval ,假設跟 3秒 比較;
- 3秒外,認為是用戶刷新的,在用戶刷新導致頁面重新加載原來的 url 時,更新 previousAccessTime ,修改 url,導致重新加載了一個新的頁面,這個時候的 時間-previousAccessTime 通常小於 3秒,所以適用下一條;
- 3秒內,就判斷是 代碼修改 url 導致的,所以不再去修改 url,避免了循環;
- 如果網速慢,導致了修改 url 重新加載的時間超過了3秒,那會重復,導致循環;
- 如果把時間改成譬如 10 秒,減少循環的可能,那么用戶在 10秒內的刷新,就不會刷新。
后兩點是缺點,當然可以通過其他方式去優化,比如,
- 調整這個 interval
- 把這個腳本放在最前面執行,減小網速慢的影響;
參考: