# 監聽 localStorage 事件：如何在同一頁面內偵測變更

## 本篇要解決的問題

我們有時會把資訊存在瀏覽器的空間裡，像是 [Cookies](https://www.letswrite.tw/client-storage-cookie/)、[Local Storage](https://www.letswrite.tw/client-storage-local/)、[IndexedDB](https://www.letswrite.tw/client-storage-idb/)。

Local Storage 原生的 `storage` 事件主要用於跨分頁同步，如下：

```js
window.addEventListener("storage", () => {});
```

但如果想要在同一個頁面內監聽變更，就需要手動覆寫 `localStorage` 方法。

---

## localStorage event listener

我們可以透過 `Storage.prototype` 覆寫 `setItem` 等方法，並在其中加入 [CustomEvent](https://www.letswrite.tw/custom-event/) 來觸發變更事件。

```js
// 保存原始方法
Storage.prototype._setItem = Storage.prototype.setItem;
Storage.prototype._getItem = Storage.prototype.getItem;
Storage.prototype._removeItem = Storage.prototype.removeItem;
Storage.prototype._clear = Storage.prototype.clear;

// 覆寫 setItem
Storage.prototype.setItem = function(key, value) {
    const oldValue = this._getItem(key);
    this._setItem(key, value);
        
    const evt = new CustomEvent('storagechange', {
        detail: {
            type: 'set',
            key: key,
            newValue: value,
            oldValue: oldValue
        }
    });
    window.dispatchEvent(evt);
};

// 覆寫 getItem
Storage.prototype.getItem = function(key) {
    const value = this._getItem(key);
    
    const evt = new CustomEvent('storagechange', {
        detail: {
            type: 'get',
            key: key,
            value: value
        }
    });
    window.dispatchEvent(evt);
    
    return value;
};

// 覆寫 removeItem
Storage.prototype.removeItem = function(key) {
    const oldValue = this._getItem(key);
    this._removeItem(key);
    
    const evt = new CustomEvent('storagechange', {
        detail: {
            type: 'remove',
            key: key,
            oldValue: oldValue
        }
    });
    window.dispatchEvent(evt);
};

// 覆寫 clear
Storage.prototype.clear = function() {
    this._clear();
    
    const evt = new CustomEvent('storagechange', {
        detail: {
            type: 'clear'
        }
    });
    window.dispatchEvent(evt);
};

// 監聽事件
window.addEventListener('storagechange', e => {
    console.log('LocalStorage 變更:', e.detail);
});
```
