---
# System prepended metadata

title: 根據滾動改變樣式（透過 IntersectionObserver 觀察交集）
tags: [javascript, vue.js]

---

## 成果
當按鈕撞到頂端後，改變樣式。

![截圖 2023-12-28 下午1.20.29](https://hackmd.io/_uploads/ByJaHYqDp.png)

![截圖 2023-12-28 下午1.20.45](https://hackmd.io/_uploads/rJKaSF9wT.png)

## 原理
在想要改變樣式的 DOM 上面放一個用來確認視窗位置的 target_DOM，利用 `IntersectionObserver` （[文件說明](https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver)）去建立一個觀測器來觀測 target_DOM，觀測 target_DOM 是否和視窗交集和對應的行為。

## 實作
```javascript
...
<div ref="target"></div>
// 放一個監測用的 target_DOM
...
<base-button :class="{ 'change-opacity': isFixed, hidden: !isFixed }"></base-button>
// 要改變樣式的 DOM
...
```
```javascript
const target = ref<HTMLElement | null>(null);
const isFixed = ref(false);
let observer: IntersectionObserver | null = null;
onMounted(() => {
  observer = new IntersectionObserver(([entry]) => {
    isFixed.value = !entry.isIntersecting;
  });
  if (target.value) {
    observer.observe(target.value);
  }
});
// 創建一個新的 IntersectionObserver 來監視 target 元素是否進入視窗。
// 如果 target 元素進入視窗，則 isFixed.value 會被設置為 false；
// 如果 target 元素離開視窗，則 isFixed.value 會被設置為 true。

onUnmounted(() => {
  if (observer && target.value) {
    observer.unobserve(target.value);
  }
});
// 在組件卸載（unmounted）時，停止監視 target 元素。
// 避免在組件卸載後仍然監視元素，這可能會導致記憶體洩漏。
```
```css
.change-opacity {
  opacity: 0.5;
}
.change-opacity:hover {
  opacity: 1;
}
```