Vue TypeScript プロジェクトでの Emits イベントの使用方法

0716eee1e7572ec3ec29e1e3028bee67.jpeg

Vue は、素晴らしい Web アプリケーションを構築するための、最も柔軟性が高く、柔軟で強力な JavaScript フレームワークの 1 つです。Vue の最も重要な概念と主要な機能の 1 つは、アプリケーション コンポーネント間の通信を容易にする機能です。Vue の「エミット」の概念を深く掘り下げて、親コンポーネントと子コンポーネント間の通信がどのように流動的かつシームレスな方法で可能になるかを見てみましょう。

Vue のエミットとは何ですか

Vue アプリケーション アーキテクチャの中核となる概念の 1 つは、コンポーネント間の親子関係です。多くの場合、親コンポーネントは子コンポーネントと対話する必要があり、その逆も同様です。私たちはこの概念を活用して、複雑で高度にインタラクティブなユーザー インターフェイスを作成します。props は親コンポーネントから子コンポーネントへのデータ フローを作成しますが、「emits」は子コンポーネントから親コンポーネントへのデータ フローを作成します。

基本的に、「エミット」は、子コンポーネントが親コンポーネントと通信できるようにする Vue の概念です。Vue でエミットを使用する場合、データ (オプション) を含むカスタム イベントを親コンポーネントにエミットできます。親コンポーネントはイベントをリッスンし、それに応じて独自の「応答」を処理できます。これは、子コンポーネントと親コンポーネント間のシームレスな通信を促進する強力なメカニズムです。

エミットが役立つ理由

エミットは、コンポーネントが親コンポーネントと対話するための構造化された分離された方法を提供します。これにより、保守と拡張が容易なアプリケーションが作成されます。エミットを活用することで、親コンポーネントに緊密に結合せずに再利用可能な子コンポーネントを作成でき、さまざまなコンテキストで使用できるようになります。

エミットは、子コンポーネントと親コンポーネントの間の高度な分離を達成する上で重要な役割を果たします。子コンポーネントが親コンポーネントにイベントを発行する場合、親コンポーネントの状態を直接操作したり、親コンポーネントのメソッドを呼び出したりすることはありません。代わりに、エミッターは、親コンポーネントがこれらのイベントを処理する方法を決定できるようにする抽象化レイヤーを提供します。私の意見では、この関心の分離は、より保守しやすく拡張可能なアーキテクチャに貢献します。

コンポーネント通信

Vue はコンポーネント化されたアーキテクチャに従っており、ユーザー インターフェイスをコンポーネントとも呼ばれる小さな自己完結型のユニットに分割します。コンポーネントをネストして組み合わせて、複雑なアプリケーションを構築できます。ただし、コンポーネントがネストされ、アプリケーションが成長するにつれて、コンポーネント間の通信が不可欠になります。コンポーネント通信により、さまざまなコンポーネントがデータを交換し、アクションをトリガーし、アプリケーション全体で一貫したアプリケーション状態を維持できるようになります。

Vue で通信するコンポーネントを取得する方法の簡単な例を見てみましょう。

サブアセンブリ

<template>
 <button @click="sendMessageToParent">Send Message to Parent</button>
</template>

<script setup>
import { defineEmits } from 'vue';

const emit = defineEmits(['messageToParent']);

const sendMessageToParent = () => {
const message = 'Hello from child!';
emit('messageToParent', message);
}
</script>

親コンポーネント

<template>
  <div>
    <child-component @message-to-parent="handleMessageFromChild" />
    <p>Message from child: {
    
    { messageFromChild }}</p>
  </div>
</template>

<script setup>
import ChildComponent from './ChildComponent.vue';
import { ref } from 'vue';

const messageFromChild = ref('');

const handleMessageFromChild = (message) => {
  messageFromChild.value = message;
}
</script>

この例では、ボタンがクリックされたときにメッセージ ペイロードを含む messageToParent というカスタム イベントを発行する ChildComponent があります。ParentComponent は、発行されたイベントをリッスンし、受信したメッセージ ( messageFromChild ) でその状態を更新します。

ChildComponent で [親にメッセージを送信] ボタンをクリックすると、sendMessageToParent 関数が実行され、ペイロードとして「Hello from child!」メッセージを含むカスタム イベントが発行されます。

ParentComponent は、テンプレートの @messageToParent 属性を介して発行されたイベントを受け取り、handleMessageFromChild 関数を使用してそれを処理します。その後、メッセージ ペイロードは messageFromChild 参照に保存され、テンプレートが自動的に更新されて、子コンポーネントからのメッセージが表示されます。

シンプルですよね?これは、Vue でコンポーネントを「相互に通信」させる方法を示しています。文字列をペイロードとして送信することに限定されず、オブジェクトや配列などの複雑な型を送信することもできます。

Typescript で型推論を正しく使用する方法

エミットを使用する場合の「欠点」の 1 つは、カスタム イベントをエミットするときに、子コンポーネントが何をエミットするか必ずしもわからないことです。この不確実性により、データ型や実行時エラーに関する潜在的な問題が発生する可能性があります。幸いなことに、Vue 3 のコンポジション API と TypeScript を組み合わせることで、この問題に対する非常に強力な解決策が提供されます。エミットを適切に入力することで、タイプ セーフを確保し、コードの明瞭さを向上させ、Vue アプリケーションの保守を容易にすることができます。

Vue 3 のコンポジション API とスクリプト セットアップを使用して、TypeScript でエミットを適切に入力する方法を見てみましょう。

サブコンポーネント (TypeScript を使用):

<template>
  <button @click="sendDataToParent">Send Data to Parent</button>
</template>

<script setup lang="ts">
import { defineEmits } from 'vue';

// Define the interface for the emitted object 
// (Ideally a shared interface for both components)
// This could event get exported, fot the parent component can import it
interface ItemData {
  id: number;
  name: string;
  quantity: number;
}

const emit = defineEmits<{
  // Define the emitted event and its payload type
  (event: 'dataToParent', payload: ItemData[]): void;
}>();

function sendDataToParent() {
  const payload: ItemData[] = [
    { id: 1, name: 'Item 1', quantity: 3 },
    { id: 2, name: 'Item 2', quantity: 5 },
    { id: 3, name: 'Item 3', quantity: 2 },
  ];

  emit('dataToParent', payload);
}
</script>

親コンポーネント: (TypeScript を使用)

<template>
  <div>
    <test-child @data-to-parent="handleDataFromChild" />
    <div v-if="itemsFromChild.length">
      <p v-for="item in itemsFromChild" :key="item.id">Item: {
    
    { item.name }} | Quantity: {
    
    { item.quantity }}</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import TestChild from '@/TestChild.vue';

// Define the interface for the emitted object 
// (Ideally a shared interface for both components)
interface ItemData {
  id: number;
  name: string;
  quantity: number;
}

const itemsFromChild = ref<ItemData[]>([]);

const handleDataFromChild = (payload: ItemData[]) => {
  itemsFromChild.value = payload;
};
</script>

TypeScript の機能を活用することで、コンポーネント間の通信が正確でタイプセーフであることを保証できます。インターフェイスと正確なペイロード タイプ定義を使用することで、コードの完成性とアプリケーション全体の保守性を向上させながら、開発中に潜在的なバグを検出することができました。

仕上げる

記事のスペースが限られているため、今日の内容はここで共有します。記事の最後に、記事の作成は簡単ではないことを思い出していただきたいと思います。私の共有が気に入っていただけましたら、忘れないでください。より多くの人が困っているように、いいねや転送をしてください。同時に、フロントエンドテクノロジーについてもっと知識を得たい場合は、私をフォローすることを歓迎します。あなたのサポートが私にとって共有する最大の動機になります。今後もより多くのコンテンツを出力していきますので、ご期待ください。

ファンの特典

美しい BootStrap 5 バックグラウンド管理ソース コードを共有する

おすすめ

転載: blog.csdn.net/Ed7zgeE9X/article/details/132613551