🏠 ホーム
フロントエンド
PHP
Go言語
プログラミングの理解
プログラマーへの道
Google API

Vue.js 開発中に学んだリアクティブデータとコンポーネント間の通信

  プログラミング >     フロントエンド >  

Vue.js を使った開発では、リアクティブデータの管理やコンポーネント間の通信が重要な要素となります。本記事では、Vue.js の v-modelemitprops の使い方を中心に、実際に経験したトラブルシューティングとその解決方法を紹介します。


問題の背景: 親子間でのデータの同期がうまくいかない

あるプロジェクトで、親コンポーネントから子コンポーネントにデータを渡し、さらに子コンポーネントで編集したデータを親に戻す必要がありました。以下のようなコードで、aliasImgaliasName を管理しようとしました。

親コンポーネント

<template>
  <input type="text" v-model="aliasName" placeholder="グループ中の自分の名前">
  <PeopleImg v-model="aliasImg" />
  <button @click="join">▶️</button><br>
</template>

<script setup>
import { ref } from "vue";
import PeopleImg from "./PeopleImg.vue";

const aliasName = ref(""); 
const aliasImg = ref("");  

async function join() {
  console.log(aliasImg.value); 
  if (!confirm("実行▶️")) {
    return;
  }
}
</script>

子コンポーネント

const props = defineProps({
  alias: Object,
  modelValue: String,
});

const emit = defineEmits(["update:modelValue"]);

const registerCombination = () => {
  aliasImg.value = "emoji, color";
  emit("update:modelValue", aliasImg.value); // 親にデータを通知
};

問題の発生

子コンポーネントでデータが更新されても、親コンポーネント側の aliasImg に反映されませんでした。console.log で確認すると、子では値が存在するのに親には渡っていません。


解決方法

1. emit の定義がない場合

子コンポーネントで defineEmits が定義されていないと、親にデータを送ることができません。このコードでは defineEmits を使って update:modelValue イベントを明示的に定義します。

const emit = defineEmits(["update:modelValue"]);

2. registerCombination のトリガーがない

データの更新が行われる関数が親コンポーネントから呼び出されないと、emit が発火しません。以下のようにトリガーを確実に動かす必要があります。

<button @click="registerCombination">Update</button>

複数の v-model を使う場合

Vue 3 では複数の v-model を使うことができます。その場合、それぞれの v-model にプロパティ名を指定する必要があります。

親コンポーネント

<template>
  <PeopleImg v-model:alias="aliasImg" v-model:other="otherValue" />
</template>

<script setup>
import { ref } from "vue";
import PeopleImg from "./PeopleImg.vue";

const aliasImg = ref("");
const otherValue = ref("");
</script>

子コンポーネント

const props = defineProps({
  alias: String,
  other: String,
});

const emit = defineEmits(["update:alias", "update:other"]);

const updateAlias = (value) => {
  emit("update:alias", value);
};

const updateOther = (value) => {
  emit("update:other", value);
};

IndexedDB との連携とエラー処理

開発中にブラウザ拡張機能 IndexedDBedit が原因で、IndexedDB のデータが破損していることに気付きました。IndexedDB にアクセスする際には、適切なエラーハンドリングが重要です。

IndexedDB のアクセス例

async function getIDB(table, id) {
  try {
    const db = await openDatabase();
    const transaction = db.transaction([table], "readonly");
    const objectStore = transaction.objectStore(table);
    const getRequest = objectStore.get(id);

    return new Promise((resolve, reject) => {
      getRequest.onsuccess = (event) => {
        const data = event.target.result;
        data ? resolve(data) : reject(new Error(`${table} by ${id} not found`));
      };
      getRequest.onerror = (event) => {
        reject(new Error(`Error getting data: ${event.target.error}`));
      };
    });
  } catch (error) {
    console.error("Error in getIDB:", error);
    throw error;
  }
}

学びとベストプラクティス

  1. v-model の正しい設定:

    • 子コンポーネントで emit を適切に定義。
    • 親から渡されたデータを常にリアクティブにする。
  2. 非同期処理とエラーハンドリング:

    • IndexedDB など非同期データを扱う際は、エラーハンドリングを徹底。
    • ブラウザの拡張機能による影響を考慮する。
  3. 複数の v-model:

    • 名前付きの v-model を活用して、複数のデータを管理する。

まとめ

Vue.js を使った開発では、親子間のデータ同期やリアクティブデータの管理が重要です。本記事で紹介したテクニックや解決方法を活用すれば、より効率的な開発ができるでしょう。皆さんもぜひ試してみてください! 🎉


いかがでしょうか?必要に応じて調整もできますので、フィードバックがあれば教えてください! 😊

登録日:

更新日:

by

コメント         tweetでコメント