Skip to content

🎧 useEventListener - イベントリスナーの神器

🌟 紹介

あなたのコンポーネントが賢明な世話人のように、適切なタイミングで様々なイベントを自動的にリッスンし、離れるときには優雅に掃除してくれることを想像してください。useEventListener はまさにそのような親切なアシスタントです!

これはコンポーネントの mountedactivated の際に自動的にイベントをバインドし、unmounteddeactivated の際に自動的にイベントをアンバインドします。手動でイベントリスナーを管理する煩わしさから解放されます。ウィンドウサイズの変化、マウスクリック、キーボード入力など、どんなイベントも簡単に処理できます!

🚀 コードデモ

基本的な使い方 - ウィンドウイベントのリッスン

js
import { ref } from 'vue';
import { useEventListener } from '@vant/use';

export default {
  setup() {
    // 🪟 ウィンドウサイズ変化のリッスン
    useEventListener('resize', () => {
      console.log('ウィンドウサイズが変わりました!');
    });

    // 📱 デバイスの向き変化のリッスン
    useEventListener('orientationchange', () => {
      console.log('デバイスの向きが変わりました!');
    });

    // ⌨️ キーボードイベントのリッスン
    useEventListener('keydown', (event) => {
      if (event.key === 'Escape') {
        console.log('ユーザーがESCキーを押しました');
      }
    });
  },
};

ターゲット要素を指定 - 精確なリッスン

js
import { ref, onMounted } from 'vue';
import { useEventListener } from '@vant/use';

export default {
  setup() {
    const buttonRef = ref();
    const containerRef = ref();

    onMounted(() => {
      // 🎯 特定ボタンのクリックをリッスン
      useEventListener(
        'click',
        () => {
          console.log('ボタンがクリックされました!');
        },
        { target: buttonRef }
      );

      // 📦 コンテナのスクロールイベントをリッスン
      useEventListener(
        'scroll',
        (event) => {
          console.log('コンテナのスクロール位置:', event.target.scrollTop);
        },
        { target: containerRef }
      );
    });

    return {
      buttonRef,
      containerRef,
    };
  },
};

手動でのクリーンアップ - 柔軟な制御

js
import { ref } from 'vue';
import { useEventListener } from '@vant/use';

export default {
  setup() {
    const isListening = ref(true);

    // 🧹 クリーンアップ関数を取得
    const cleanup = useEventListener('resize', () => {
      console.log('ウィンドウサイズが変更されました');
    });

    // 🎛️ リッスン状態を動的に制御
    const toggleListener = () => {
      if (isListening.value) {
        cleanup(); // リッスンを停止
        isListening.value = false;
      } else {
        // リッスンを再開
        useEventListener('resize', () => {
            console.log('ウィンドウの変化のリッスンを再開しました');
          });
          isListening.value = true;
        }
      };

    return {
      isListening,
      toggleListener,
    };
  },
};

高度な設定 - パフォーマンスの最適化

js
import { ref } from 'vue';
import { useEventListener } from '@vant/use';

export default {
  setup() {
    const scrollContainer = ref();

    // 🚀 passive モードを使用してスクロールパフォーマンスを最適化
    useEventListener(
      'scroll',
      (event) => {
        // preventDefault を呼び出さないため、パフォーマンスが向上します
        console.log('スクロール位置:', event.target.scrollTop);
      },
      {
        target: scrollContainer,
        passive: true, // スクロールパフォーマンスを向上
      }
    );

    // 🎯 キャプチャモードを使用
    useEventListener(
      'click',
      (event) => {
        console.log('キャプチャフェーズでクリックイベントを処理');
      },
      {
        target: document.body,
        capture: true, // キャプチャフェーズでトリガー
      }
    );

    return {
      scrollContainer,
    };
  },
};

モバイル対応 - タッチイベント

js
import { ref } from 'vue';
import { useEventListener } from '@vant/use';

export default {
  setup() {
    const touchArea = ref();
    const startPos = ref({ x: 0, y: 0 });

    // 👆 タッチ開始
    useEventListener(
      'touchstart',
      (event) => {
        const touch = event.touches[0];
        startPos.value = {
          x: touch.clientX,
          y: touch.clientY,
        };
      },
      { target: touchArea, passive: true }
    );

    // 👆 タッチ移動
    useEventListener(
      'touchmove',
      (event) => {
        const touch = event.touches[0];
        const deltaX = touch.clientX - startPos.value.x;
        const deltaY = touch.clientY - startPos.value.y;
        
        console.log('スライド距離:', { deltaX, deltaY });
      },
      { target: touchArea, passive: true }
    );

    return {
      touchArea,
    };
  },
};

📚 API リファレンス

型定義

ts
type Options = {
  target?: EventTarget | Ref<EventTarget>;
  capture?: boolean;
  passive?: boolean;
};

function useEventListener(
  type: string,
  listener: EventListener,
  options?: Options,
): () => void;

パラメータの説明

パラメータ説明デフォルト値
type🎯 リッスンするイベントタイプ('click', 'resize', 'scroll' など)string-
listener🎧 イベントコールバック関数EventListener-
options⚙️ オプションの設定項目Options-

Options 設定

パラメータ説明デフォルト値
target🎯 イベントをバインドするターゲット要素EventTarget | Ref<EventTarget>window
capture📥 イベントキャプチャフェーズでトリガーするかどうかbooleanfalse
passive🚀 true に設定すると、listenerpreventDefault を呼び出さないことを示し、パフォーマンスが向上しますbooleanfalse

戻り値

説明
() => void🧹 クリーンアップ関数、呼び出すとイベントリスナーが削除されます

🎯 実際のアプリケーションシナリオ

📱 モバイル端末のジェスチャー認識

js
// 左右スワイプ切り替えの実装
const useSwipeGesture = (onSwipeLeft, onSwipeRight) => {
  let startX = 0;
  
  useEventListener('touchstart', (e) => {
    startX = e.touches[0].clientX;
  }, { passive: true });
  
  useEventListener('touchend', (e) => {
    const endX = e.changedTouches[0].clientX;
    const diff = startX - endX;
    
    if (Math.abs(diff) > 50) {
      diff > 0 ? onSwipeLeft() : onSwipeRight();
    }
  }, { passive: true });
};

🖥️ レスポンシブレイアウトのリッスン

js
// 画面サイズの変化をリッスンし、動的にレイアウトを調整
const useResponsiveLayout = () => {
  const isMobile = ref(window.innerWidth < 768);
  
  useEventListener('resize', () => {
    isMobile.value = window.innerWidth < 768;
  });
  
  return { isMobile };
};

⌨️ ショートカットキーシステム

js
// グローバルショートカットキーの実装
const useHotkeys = () => {
  useEventListener('keydown', (e) => {
    if (e.ctrlKey && e.key === 's') {
      e.preventDefault();
      console.log('保存ショートカットキーがトリガーされました');
    }
  });
};

💡 ベストプラクティス

✅ 推奨される方法

js
// 1. passive を使用してスクロールパフォーマンスを最適化
useEventListener('scroll', handler, { passive: true });

// 2. グローバルではなく特定の要素をリッスンする
useEventListener('click', handler, { target: buttonRef });

// 3. 必要なときに手動でクリーンアップする
const cleanup = useEventListener('resize', handler);
// ある条件下でクリーンアップ
if (shouldCleanup) cleanup();

❌ 避けるべき使い方

js
// ❌ イベントハンドラーで時間のかかる操作を実行しない
useEventListener('scroll', () => {
  // 複雑な計算は避ける
  heavyComputation();
});

// ❌ タイマーなどの副作用のクリーンアップを忘れない
useEventListener('click', () => {
  setInterval(() => {
    // メモリリークの原因になる可能性がある
  }, 1000);
});

🛠️ デバッグのヒント

イベントリスナーの状態チェック

js
// デバッグ情報を追加
const cleanup = useEventListener('click', (e) => {
  console.log('イベントがトリガーされました:', {
    type: e.type,
    target: e.target,
    timestamp: Date.now(),
  });
});

// 正しくクリーンアップされているか確認
onUnmounted(() => {
  console.log('コンポーネントがアンマウントされました、イベントリスナーのクリーンアップを確認');
});

性能监控

js
// イベントの頻度を監視
let eventCount = 0;
useEventListener('scroll', () => {
  eventCount++;
  if (eventCount % 100 === 0) {
    console.log(`スクロールイベントが ${eventCount} 回トリガーされました`);
  }
}, { passive: true });

📚 関連ドキュメント

🎯 イベント処理関連

📱 モバイル関連

🎨 UI インタラクション関連

🛠️ 開発ツール

📖 実践ケース

Vant に基づく企業向けモバイルソリューション