Vue.jsのコンポーネント間でデータを渡す方法
公開: 2022-03-10コンポーネント間でデータを共有することは、VueJSのコア機能の1つです。 これにより、よりモジュール化されたプロジェクトを設計し、データスコープを制御し、アプリ全体でデータの自然な流れを作成できます。
Vueアプリ全体を1つのコンポーネントで作成している場合を除いて(これは意味がありません)、コンポーネント間でデータを共有する必要がある状況に遭遇します。
このチュートリアルを終えると、これを行うための3つの方法がわかります。
- 小道具を使用して親から子にデータを共有し、
- カスタムイベントを発行して、子から親にデータを共有し、
- Vuexを使用してアプリレベルの共有状態を作成します。
わかりました—すぐに始めましょう!
Nuxtでアプリを構築する
Spotifyを使用すると、友達はあなたが妨害しているものをチェックできます。 インターネットの他の部分もあなたのアルゴリズムを体験できるとしたらどうでしょうか? Vue.jsとNuxtを使用して、Spotifyで聴いているものを共有するための独自のアプリを作成する方法を学びます。 関連記事を読む→
1.小道具を使用して親から子にデータを共有する
VueJSの小道具は、コンポーネント間でデータを共有するための最も簡単な方法です。 小道具は、コンポーネントに与えることができるカスタム属性です。 次に、テンプレートで、これらの属性に値を指定できます。— BAM —親から子コンポーネントにデータを渡します。
たとえば、ユーザープロファイルページで作業していて、子コンポーネントにユーザー名propを受け入れさせたいとします。 2つのコンポーネントが必要です。
- 小道具を受け入れる子コンポーネント。これを
AccountInfo.vue
と呼びましょう。 - 小道具を渡す親コンポーネント。これを
ProfilePage.vue
と呼びましょう。
AccountInfo.vue
内で、propsオプションを使用して受け入れるpropsを宣言できます。 そこで、コンポーネントオプション内で、次のようにしましょう。
// AccountInfo.vue <template> <div id='account-info'> {{username}} </div> </template> <script> export default { props: ['username'] } </script>
次に、親( ProfilePage.vue
)から実際にデータを渡すために、カスタム属性のように渡します。
// ProfilePage.vue <account-info username='matt' />
ここでページをロードすると、 AccountInfo
コンポーネントがその親から渡された値を適切にレンダリングしていることがわかります。
他のVueJSディレクティブを操作する場合と同様に、v-bindを使用して小道具を動的に渡すことができます。 たとえば、usernamepropを変数と等しくなるように設定するとします。 これは、v-bindディレクティブの省略形(または単に:
略して)を使用することで実現できます。 コードは次のようになります。
<template> <div> <account-info :username="user.username" /> </div> </template> <script> import AccountInfo from "@/components/AccountInfo.vue"; export default { components: { AccountInfo }, data() { return { user: { username: 'matt' } } } } </script>
これは、データを変更でき、その値を使用する子プロップも更新されることを意味します。
ヒント:常に小道具を確認してください
より明確なVueコードを記述したい場合、重要なテクニックは小道具を検証することです。 つまり、これは、小道具の要件(つまり、タイプ、形式など)を指定する必要があることを意味します。 これらの要件の1つが満たされない場合(たとえば、小道具に間違ったタイプが渡された場合)、Vueは警告を出力します。
ユーザー名propに文字列のみを受け入れさせたいとしましょう。 小道具オブジェクトを次のように変更する必要があります。
export default { props: { username: String } }
大規模なVueアプリで作業する場合、またはプラグインを設計する場合は、小道具の確認が不可欠です。 全員が同じページにいることを確認し、意図したとおりに小道具を使用するのに役立ちます。
小道具に含めることができる検証の完全なリストについては、詳細なレビューのために公式ドキュメントを確認することを強くお勧めします。
ヒント:プロップの命名規則に従ってください
VueJSスタイルガイドによると、小道具に名前を付ける最良の方法は、スクリプトで小道具を宣言するときにcamelCase
を使用し、テンプレートコードで小道具を参照するときにケバブケースを使用することです。
この背後にある理由は、実際には非常に単純です。 Javascriptでは、 camelCase
は標準の命名規則であり、HTMLではkebab-caseです。
したがって、Vueは、各言語の規範に固執することをお勧めします。 ありがたいことに、Vueは2つのスタイル間で自動的に変換できるため、開発者が追加でセットアップする必要はありません。
// GOOD <account-info :my-username="user.username" /> props: { myUsername: String } // BAD <account-info :myUsername="user.username" /> props: { "my-username": String }
2.子から親にデータを共有するためのイベントの発行
階層を下ってデータを渡すことができたので、別の方法でデータを渡します。子コンポーネントから親に渡します。 小道具は使用できませんが、カスタムイベントとリスナーは使用できます。
すべてのVueインスタンスは、イベントをトリガーする.$emit(eventName)
メソッドを呼び出すことができます。 次に、v-onディレクティブを使用して、他のイベントと同じ方法でこのイベントをリッスンできます。
カスタムイベントの作成
ユーザー名を変更するボタンを追加して、ユーザープロファイルの例を作成してみましょう。 子コンポーネント( AccountInfo.vue
)内に、ボタンを作成しましょう。
次に、このボタンをクリックすると、 changeUsername
というイベントが発行されます。
<template> <div id='account-info'> <button @click='changeUsername()'>Change Username</button> {{username}} </div> </template> <script> export default { props: { username: String }, methods: { changeUsername() { this.$emit('changeUsername') } } } </script>
親の内部で、このイベントを処理し、 user.username
変数を変更します。 前に説明したように、v-onディレクティブまたは略して「@」を使用してイベントをリッスンできます。
<template> <div> <account-info :username="user.username" @changeUsername="user.username = 'new name'"/> </div> </template>
試してみましょう。 ボタンをクリックすると、ユーザー名が「新しい名前」に変わることがわかります。
ヒント:カスタムイベントは引数を受け入れることができます
イベントに引数を渡すための最も一般的なユースケースは、子コンポーネントがそのプロパティに特定の値を設定できるようにする場合です。 コンポーネント自体から小道具の値を直接編集する必要はありません。
ただし、幸いなことに、カスタムイベントでpass引数を使用して、親コンポーネントに値を変更させることができます。
値を渡すことができるようにchangeUsername
イベントを変更するとします。
$emit
メソッドは、引数にオプションの2番目のパラメーターを取ります。 したがって、イベントの名前の後に新しいユーザー名の値を追加するだけです。
this.$emit('changeUsername', 'mattmaribojoc')
次に、親コンポーネントで、特別な$event
変数を使用してこれらの値にインラインでアクセスするか、パラメーターを受け取るハンドラーメソッドを記述します。
<account-info :username="user.username" @changeUsername="user.username = $event"/> OR <account-info :username="user.username" @changeUsername="changeUsername($event)"/> export default { ... methods: { changeUsername (username) { this.user.username = username; } } }
3.Vuexを使用してアプリケーションレベルの共有状態を作成する
わかりました—親/子間でデータを共有する方法は知っていますが、他のコンポーネントについてはどうでしょうか。 データを渡す場合、非常に複雑な階層システムを作成する必要がありますか?
ありがたいことにありません。 素晴らしいVuex状態管理ライブラリは、何年にもわたって開発者の生活を簡素化してきました。 つまり、すべてのコンポーネントからアクセスできる一元化されたデータストアを作成します。
以前に使用した方法(小道具/イベントの発行)では、各コンポーネントに独自のデータ状態があり、コンポーネント間で共有します。 ただし、Vuexでは、すべての共有データを単一の状態に抽出して、各コンポーネントが簡単にアクセスできるようにすることができます。 この共有状態はストアと呼ばれます。
試してみましょう。
VuexはVueのコアコードとは別のものであるため、最初にインストールしてプロジェクトにインポートする必要があります。 まず、プロジェクトCLI内でnpm install vuex --save
を実行する必要があります。
次に、次のコードを含むindex.jsファイルを使用してsrc / storeフォルダーを作成します。
// store/index.js import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); export default new Vuex.Store({ state: {}, getters: {}, mutations: {}, actions: {} });
これをルートVueインスタンスに含めるには、store / index.jsファイルをインポートして、Vueコンストラクターに渡す必要があります。
// main.js import store from "./store"; new Vue({ store, ...
コンポーネント内のVueストアへのアクセス
VuexストアをルートVueインスタンスに追加したため、ルートのすべての子に注入されます。 コンポーネントからストアにアクセスする場合は、 this.$store
を使用できます。
それでは、Vuecストアの4つの部分のそれぞれの詳細を詳しく見ていきましょう。
1.状態
Vuex状態は、アプリケーションレベルのデータを含むオブジェクトです。 すべてのVueインスタンスがこのデータにアクセスできるようになります。
私たちのストアでは、さらにいくつかのユーザープロファイルデータを格納するユーザーオブジェクトを作成しましょう。
export default new Vuex.Store({ state: { user: { username: 'matt', fullName: 'Matt Maribojoc' } }, getters: {}, mutations: {}, actions: {} });
このようなインスタンスコンポーネント内でこのデータにアクセスできます。
mounted () { console.log(this.$store.state.user.username); },
2.ゲッター
Vuexゲッターを使用して、状態データの変更された値を返します。 ゲッターを考える良い方法は、それらを計算されたプロパティのように扱うことです。 たとえば、計算されたプロパティのようなゲッターは、結果をキャッシュし、依存関係が変更された場合にのみ再評価します。
以前のストアに基づいて、フルネーム属性に基づいてユーザーの名を返すメソッドを作成するとします。
getters: { firstName: state => { return state.user.fullName.split(' ')[0] } }
Vuexゲッタープロパティは、 store.getters
オブジェクトのコンポーネントで使用できます。
mounted () { console.log(this.$store.getters.firstName); }
ヒント:デフォルトのゲッター引数を知っている
デフォルトでは、Vuexゲッターは2つの引数を受け入れます。
- state —アプリケーションの状態オブジェクト。
- getters — store.gettersオブジェクト。これは、ストア内の他のゲッターを呼び出すことができることを意味します。
宣言するすべてのゲッターには、最初の状態引数が必要です。 また、コードの設計方法に応じて、ゲッターは2番目の「getters」引数を使用して相互に参照できます。
フルネームの状態プロパティからファーストネームの値を削除するだけのラストネームゲッターを作成しましょう。 この例では、stateオブジェクトとgettersオブジェクトの両方が必要になります。
lastName (state, getters) { return state.user.fullName.replace(getters.firstName, ''); }
ヒント:カスタム引数をVuexゲッターに渡す
ゲッターのもう1つの優れた機能は、ゲッターにメソッドを返すようにすることで、カスタム引数を渡すことができることです。
prefixedName: (state, getters) => (prefix) => { return prefix + getters.lastName; } // in our component console.log(this.$store.getters.prefixedName("Mr."));
3.突然変異
ミューテーションは、状態オブジェクトの値を適切に変更する唯一の方法です。 注意すべき重要な詳細は、ミューテーションは同期的でなければならないということです。
ゲッターと同様に、ミューテーションは常にVuex状態プロパティを最初の引数として受け入れます。 また、ペイロードと呼ばれるカスタム引数を2番目の引数として受け入れます。
たとえば、ユーザーの名前を特定の値に変更するための変更を行いましょう。
mutations: { changeName (state, payload) { state.user.fullName = payload } },
次に、ペイロードを2番目の引数として、 store.commit
メソッドを使用してコンポーネントからこのメソッドを呼び出すことができます。
this.$store.commit("changeName", "New Name");
多くの場合、ペイロードをオブジェクトにする必要があります。 これは、ミューテーションにいくつかの引数を渡すことができることを意味するだけでなく、オブジェクトのプロパティ名のためにコードを読みやすくします。
changeName (state, payload) { state.user.fullName = payload.newName }
ペイロードを使用してミューテーションを呼び出すには、2つの異なる方法があります。
- 最初の引数としてミューテーションタイプを、2番目の引数としてペイロードを使用できます。
- タイプ用に1つのプロパティを使用し、ペイロード用に別のプロパティを使用して、単一のオブジェクトを渡すことを宣言できます。
this.$store.commit("changeName", { newName: "New Name 1", }); // or this.$store.commit({ type: "changeName", newName: "New Name 2" });
この2つがどのように機能するかには実際の違いはないので、完全に個人的な好みに依存します。 プロジェクト全体で一貫性を保つことが常に最善であることを忘れないでください。どちらを選択しても、それを維持してください。
4.アクション
Vuexでは、アクションを使用して状態を変更するため、アクションはミューテーションとかなり似ています。 ただし、アクションによって値自体が変更されることはありません。 代わりに、アクションはミューテーションをコミットします。
また、Vuexミューテーションは同期的である必要がありますが、アクションは同期的ではありません。 アクションを使用すると、たとえば、API呼び出しの後にミューテーションを呼び出すことができます。
これまで見てきたほとんどのVuexハンドラーは、状態をメインパラメーターとして受け入れますが、アクションはコンテキストオブジェクトを受け入れます。 このコンテキストオブジェクトを使用すると、Vuexストアのプロパティ(state、commit、getterなど)にアクセスできます。
これは、2秒間待機してからchangeName
ミューテーションをコミットするVuexアクションの例です。
actions: { changeName (context, payload) { setTimeout(() => { context.commit("changeName", payload); }, 2000); } }
コンポーネント内では、関数を実行するためにstore.dispatchメソッドを使用します。 ミューテーションの場合と同じように引数を渡します。 タイプを宣言し、2番目の引数でカスタム引数を渡します。
this.$store.dispatch("changeName", { newName: "New Name from Action" });
まとめ
ここで、VueJSのコンポーネント間でデータを共有するための、小道具、カスタムイベント、Vuexストアの3つの異なる方法を知っておく必要があります。
このチュートリアルが、いくつかの異なるVueメソッドとベストプラクティスについての洞察を深めるのに役立つことを願っています。 それらをプロジェクトにどのように実装したか教えてください!
参考文献
各テクニックの技術的な側面/機能をさらに深く掘り下げることに興味がある場合は、ここから始めるのが最適です。
- Vuex公式ガイドのウェブサイト
- 小道具とカスタムイベント用のVueJSドキュメント
- 「WTFはVuexですか? Vueのアプリケーションデータストアの初心者向けガイド」、Anthony Gore、Vue.js開発者