storage 變化監聽
結論先講
想在同一網頁監聽快取的變化,請使用 CustomEvent。
問題
事情是這樣的。電商網站,不是都有購物車保存商品的功能嗎?按下商品,右上角的購物車圖標,就會出現一個數字,像這樣……
好的,那麼怎做呢?每個網站都不一樣,但基本上,都要用到瀏覽器快取技術。不管那是 cookie, localStorage, sessionStorage……
問題來了:如何監聽快取的數值變化呢?
探索:DOM 操作流
如果你是用 DOM 操作流的思路,那答案就是:
- 選取購物車 DOM。
- 修改該 DOM 的數值。
也就是這樣:
const dom = document.querySelector(".shopcart");
const value = "foobar";
localStorage.setItem("shopcart", value);
dom.innerText = value;
但如果你用能切分組件、自行操作 DOM 的框架或函式庫,比方說 React, Vue 這種的話,操作 DOM 就會很麻煩、甚至可能會干擾框架的行為。
在這種情況下,你必須使用事件,操作對應的數值、然後讓框架或函式庫自行操作、呈現數值的變化。
一開始,我發現有 Window: storage event 似乎能監聽快取變化……但最後發現該事件不能監聽同一頁的快取變化:
Note: This won't work on the same page that is making the changes — it is really a way for other pages on the domain using the storage to sync any changes that are made.
此路不通。那怎麼辦?
探索:Event 操作流
後來發現,開發者其實可以自訂事件,將其綁定在指定 DOM:
const value = "foobar";
const event = new CustomEvent( "shopcarted", { detail: { value } } );
localStorage.setItem( "shopcart", value );
window.dispatchEvent( event );
// In React
class Shopcart extends React.Component {
constructor(props) {
super(props);
this.state = { cart_value: 0 };
}
shopcarted() {
window.addEventListener( "shopcarted", (e) => {
this.setState({ cart_value: e.detail.value });
});
}
componentDidMount() {
this.shopcarted();
}
render() {
return ( <div className="shopcart">{this.state.cart_value}</div> );
}
}
是的。只要設定好事件,然後在接收方寫好指定的行為,這樣就能監聽快取變化了。
參考資料
- https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event
- https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent
- https://www.codegrepper.com/code-examples/javascript/listen+to+localstorage+changes
- https://ithelp.ithome.com.tw/articles/10192175
- https://realdennis.medium.com/javascript-事件-event-da8104c5c98c
- https://juejin.cn/post/6844904069820055560
- https://stackoverflow.com/a/65348883/7162445