Astro + Swup で addEventListener が追加できないときの対処法

2024-09-21 03:00 公開

swupとは

swupでは、ページの遷移アニメーションやページの事前ロードによる最適化ができます

カーソルを合わせた時やリンクが画面に入った時に事前ロードを発生させることで、表示を高速化できます

swup ドキュメント

Astro + Swup の公式 Integration を使う

@swup/astro

この Intergration を使うと、Astroのページ遷移のアニメーションやプリロードが簡単に実現できます

インストール方法:

# pnpmの場合
pnpm install @swup/astro
// astro.config.mts
import { defineConfig } from 'astro/config'
import swup from '@swup/astro'

export default defineConfig({
  integrations: [swup()], // swup() を追加
})

Swup で移動したときに addEventListener が無効になる

このようなコードで、Astroのページにメニューを追加していました (Astroコンポーネントの説明は省略します、公式ドキュメントを見てください)

Astroテンプレートの構文

<a id="open">
  <Icon name="gravity-ui:dots-9" />
</a>
<div id="menu">
  <h2>menu</h2>
  <!-- メニューの内容 -->
  <a id="close">
    <Icon name="gravity-ui:xmark" />
  </a>
</div>

<script>
  import { gsap } from 'gsap'
  function init() {
    const open = document.getElementById('open')
    open.addEventListener('click', () => {
      gsap.to(menu, { display: 'block' })
    })
  }
  init()
</script>

(classは省略しています)

このコンポーネントを各ページのLayoutに追加して使っていたのですが、ページを移動するとmenuが押せなくなる問題が発生しました

原因は、swupで移動した際にeventListenerが初期化されてしまうからであることはすぐに分かったのですが、swupの遷移を検知して再登録(つまりinit()を実行)をするのにとても悩みました

解決策

結論から言うと、以下の方法でイベントの再登録ができました

<script>
  import { gsap } from 'gsap'
  function init() {
    const open = document.getElementById('open')
    open.addEventListener('click', () => {
      gsap.to(menu, { display: 'block' })
    })
  }
  init()
  const setup = () => {
    ;(window as any).swup.hooks.on('page:view', init)
  }
  if ((window as any).swup) {
    setup()
  } else {
    document.addEventListener('swup:enable', setup)
  }
</script>

同時に、 astro.config.mts で以下の設定を有効にします

import { defineConfig } from 'astro/config'
import swup from '@swup/astro'

// https://astro.build/config
export default defineConfig({
  integrations: [
    swup({
      globalInstance: true, // この行を追加する
    }),
  ],
})

これによって、

  1. window.swup インスタンスが登録されたことを検知して、ページが開かれたことを検知するhooksを登録
  2. ページが開かれたことを検知して init() を実行
  3. init() によって EventListener を再登録

を実行でき、ページの遷移後もメニューを開けるようになりました🎉

2日ぐらい悩みました、これをやっている人がほとんどいなかったので情報がないに等しかったです

そこで

@swup/astro

README.mdを隅々まで見返してみると、下の方にNoteとして書いてあったのです、いやー気づかなかった!

知見が見つからなかったので書いてみました!
参考になれば幸いです!!

uiro

uiro

famisics

ご覧いただきありがとうございました!