子コンポーネントを通じて親コンポーネントのプロパティを変更するための Vue のさまざまな実装方法

子コンポーネントを通じて親コンポーネントのプロパティを変更するための Vue のさまざまな実装方法

序文

実際の業務プロジェクト開発では、親コンポーネントが最初に子コンポーネントに値を渡し、その後子コンポーネントがシーンをレンダリングして表示するというシナリオがよくあります。以下に、現在の業務で遭遇して使用したいくつかの方法をまとめました。実装方法やアイデアの参考になります。誤解や他の方法がある場合は、コメント欄にメッセージを残して指導してください〜

一般的な方法

一方向の prop 転送ルールに従うことをお勧めします。基本データ型と参照データ型の両方が許容されます。

1. 親コンポーネントを介して子コンポーネントの発行イベントをリッスンしてpropを変更します。

原理:

  • 子コンポーネントの input タグの value 属性をバインドし、prop に値を割り当てます。v-model の代わりに value が使用されるため、入力値を変更しても prop には影響しません。
  • 次に、入力イベントを入力にバインドします。各入力は入力イベントをトリガーします。イベントでは、this.$emit('親がリッスンするイベント名'、変更された値) を使用して値を上方に渡します。
  • 親コンポーネントは、 on を使用して、子コンポーネントによってトリガーされたばかりの emitting イベントをリッスンし、イベントによって渡された値を親コンポーネントのデータに更新します。
  • 親コンポーネントのデータの値が更新されると、その値は prop を介して子コンポーネントに渡されるため、子コンポーネントも prop 値を同期的に更新し、ビュー レイヤーをレンダリングします。

放出する

親コンポーネントのコードは次のとおりです。

<テンプレート>
  <div style="background-color: skyblue;">
    <h3>子コンポーネントが親コンポーネントを介してイベントを発行するのをリッスンしてプロパティを変更します</h3>
    <div>親オブジェクト:{{ obj }}</div>
    <div>親メッセージ:{{ メッセージ }}</div>
    <!-- 親コンポーネントが子コンポーネントを呼び出すと、子コンポーネントによってトリガーされた放出イベントを on 経由でリッスンして値を受け取り、ユーザーを更新します -->
    <emitChild
      :obj="obj"
      :msg="メッセージ"
      @update-obj="updateObj"
      @update-msg="更新メッセージ"
    />
  </div>
</テンプレート>

<スクリプト>
'./components/emitChild' から emittingChild をインポートします。

エクスポートデフォルト{
  名前: 'emitUpdate',
  コンポーネント:
    子を放出する
  },
  データ () {
    戻る {
      オブジェクト: {
        名前: 'zhangsan'、
        年齢: 18
      },
      メッセージ: 'こんにちは'
    }
  },
  メソッド: {
    // 子コンポーネントによってトリガーされたイベントをリッスンし、データ内のオブジェクトを更新します
    updateObj (キー、newVal) {
      this.obj[キー] = newVal
    },
    // 子コンポーネントによってトリガーされたイベントをリッスンし、データ内のメッセージを更新します
    更新メッセージ (新しい値) {
      this.msg = 新しい値
    }
  }
}
</スクリプト>

サブコンポーネントコードは次のとおりです。

<テンプレート>
  <div style="background-color: pink;">
    <div>
      <span>名前を変更:</span>
      <!-- ここで、バインディング値は value です。これは、入力が主にプロパティ データを表示するために使用され、実際の変更はサブコンポーネント内にないためです。サブコンポーネントは変更トリガー ソースとしてのみ使用されます -->
      <!-- 入力イベントをトリガー ソースのエントリ ポイントとしてバインドします -->
      <input type="text" :value="obj.name" @input="updateObj($event, 'name')">
    </div>
    <div>
      <span>年齢を変更:</span>
      <input type="text" :value="obj.age" @input="updateObj($event, 'age')">
    </div>
    <div>
      <span>メッセージを変更:</span>
      <input type="text" :value="msg" @input="updateMsg($event.target.value)">
    </div>
  </div>
</テンプレート>

<スクリプト>
エクスポートデフォルト{
  名前: 'emitUpdateChild',
  小道具: {
    オブジェクト: {
      タイプ: オブジェクト、
      デフォルト: () => {}
    },
    メッセージ: {
      タイプ: 文字列、
      デフォルト: ''
    }
  },
  メソッド: {
    // 親コンポーネントに obj を更新するよう通知する
    updateObj ($event, キー) {
      // 入力値と、更新する必要がある obj 内の対応する属性を受け取り、それを親コンポーネントに返します // 親コンポーネントは、子コンポーネントが更新する必要がある obj 内の属性値を知ることができます this.$emit('update-obj', key, $event.target.value)
    },
    // 親コンポーネントにメッセージの更新を通知する
    更新メッセージ (新しい値) {
      this.$emit('update-msg', newVal)
    }
  }
}
</スクリプト>

2. 親コンポーネントの同期修飾子と子コンポーネントの発行イベントを介してプロパティを変更する

原理:

  • 子コンポーネントの input タグの value 属性をバインドし、prop に値を割り当てます。v-model の代わりに value が使用されるため、入力値を変更しても prop には影響しません。
  • 次に、入力イベントを入力にバインドします。各入力は入力イベントをトリガーします。イベントでは、this.$emit('親がリッスンするイベント名'、変更された値) を使用して値を上方に渡します。
  • 親コンポーネントが子コンポーネントを呼び出してプロパティを渡す場合、プロパティの後に .sync を追加して、イベントによって渡された値を親コンポーネントのデータに更新します。これは、sync が実際にはコード @Listener child triggered event name = "property name in parent data = value passing by emitting (ie $event)" を実行することと同じであるためです。
  • 親コンポーネントのデータの値が更新されると、その値は prop を介して子コンポーネントに渡されるため、子コンポーネントも prop 値を同期的に更新し、ビュー レイヤーをレンダリングします。

同期

親コンポーネントのコードは次のとおりです。

<テンプレート>
  <div style="background-color: skyblue;">
    <h3>親コンポーネントの同期修飾子と子コンポーネントの発行イベントを介してプロパティを変更する</h3>
    <div>親オブジェクト:{{ obj }}</div>
    <div>親メッセージ:{{ メッセージ }}</div>
    <!-- 親コンポーネントが子コンポーネントを呼び出してプロパティを渡す場合は、プロパティの後に .sync を追加するだけです -->
    <syncChild:obj.sync="obj":msg.sync="msg" />
    <!--
      同期は実際には、@listener トリガー イベント名 = "親データのプロパティ名 = エミットによって渡された値 (つまり $event)" を実行することと同じです。
      このコード -->
    <!-- 効果は次のコードと同等なので、親コンポーネントのメソッドでデータを変更するメソッドを定義する必要はありません-->
    <!--
      <同期子
        :obj="obj"
        :msg="メッセージ"
        @update-obj="obj = $event"
        @update-msg="メッセージ = $イベント"
      />
    -->
  </div>
</テンプレート>

<スクリプト>
'./components/syncChild' から syncChild をインポートします。

エクスポートデフォルト{
  名前: 'syncUpdate',
  コンポーネント:
    同期子
  },
  データ () {
    戻る {
      オブジェクト: {
        名前: 'zhangsan'、
        年齢: 18
      },
      メッセージ: 'こんにちは'
    }
  }
}
</スクリプト>

サブコンポーネントコードは次のとおりです。

<テンプレート>
  <div style="background-color: pink;">
    <div>
      <span>名前を変更:</span>
      <!-- ここで、バインディング値は value です。これは、入力が主にプロパティ データを表示するために使用され、実際の変更はサブコンポーネント内にないためです。サブコンポーネントは変更トリガー ソースとしてのみ使用されます -->
      <!-- 入力イベントをトリガー ソースのエントリ ポイントとしてバインドします -->
      <input type="text" :value="childObj.name" @input="updateObj($event, 'name')">
    </div>
    <div>
      <span>年齢を変更:</span>
      <input type="text" :value="childObj.age" @input="updateObj($event, 'age')">
    </div>
    <div>
      <span>メッセージを変更:</span>
      <input type="text" :value="msg" @input="updateMsg($event.target.value)">
    </div>
  </div>
</テンプレート>

<スクリプト>
// ここでは lodash ツールライブラリの cloneDeep ディープコピーメソッドを紹介します // 公式ドキュメントアドレス https://www.lodashjs.com/
'lodash' から { cloneDeep } をインポートします

エクスポートデフォルト{
  名前: 'emitUpdateChild',
  小道具: {
    オブジェクト: {
      タイプ: オブジェクト、
      デフォルト: () => {}
    },
    メッセージ: {
      タイプ: 文字列、
      デフォルト: ''
    }
  },
  データ () {
    戻る {
      // ここでは、prop の obj がディープ コピーによってコピーされます。主な目的は次の通りです。
      // 1. 異なるメモリアドレスを使用して 2 つのオブジェクト (参照型) を区別します // 2. 子コンポーネントのレンダリング/変更/返却を容易にするために、オブジェクト内のすべての値を保持します childObj: cloneDeep(this.obj)
    }
  },
  メソッド: {
    // 親コンポーネントに obj を更新するよう通知する
    updateObj ($event, キー) {
      // 入力値と、更新する必要がある childObj 内の対応する属性を受け取ります // 次に、childOBj を更新して親コンポーネントに渡します // 親コンポーネントは、取得した childObj をデータの obj に直接更新できます this.childObj[key] = $event.target.value
      this.$emit('update:obj', this.childObj)
    },
    // 親コンポーネントにメッセージの更新を通知する
    更新メッセージ (新しい値) {
      this.$emit('update:msg', newVal)
    }
  }
}
</スクリプト>

ヒント

これは主に参照データ型を対象とし、Vue のプロパティ検出メカニズムをバイパスします。プロジェクトの仕様でこの記述が許可されているかどうかによって異なります。

3. データを通じてプロパティを変更する

前提条件: 参照データ型のみ実装可能

原理:

  • 親コンポーネントから渡された prop を子コンポーネントの data に直接代入します。このとき、prop と data の両側の変数は同じメモリ アドレスを指しているため、データを変更することは prop を変更することと同等になります。
  • Vue2 では props を直接変更することはできませんが、今回は props ではなくデータを変更しているため、Vue はエラーをスローしません。これは、props の変更を許可しない Vue の検出メカニズムをバイパスすることと同じです。

データ

親コンポーネントのコードは次のとおりです。

<テンプレート>
  <div style="background-color: skyblue;">
    <h3>prop をデータに割り当てて変更する</h3>
    <div>親オブジェクト:{{ obj }}</div>
    <div>親メッセージ:{{ メッセージ }}</div>
    <dataChild :obj="obj" :msg.sync="msg" />
  </div>
</テンプレート>

<スクリプト>
'./components/dataChild' から dataChild をインポートします。

エクスポートデフォルト{
  名前: 'dataUpdate',
  コンポーネント:
    データ子
  },
  データ () {
    戻る {
      オブジェクト: {
        名前: 'zhangsan'、
        年齢: 18
      },
      メッセージ: 'こんにちは'
    }
  }
}
</スクリプト>

サブコンポーネントコードは次のとおりです。

<テンプレート>
  <div style="background-color: pink;">
    <div>
      <span>名前を変更:</span>
      <!-- ここでは、prop をデータに直接割り当てているため、v-model の双方向バインディングを直接使用してデータを変更できます -->
      <input type="text" v-model="dataObj.name">
    </div>
    <div>
      <span>年齢を変更:</span>
      <input type="text" v-model="dataObj.age">
    </div>
    <div>
      <span>メッセージを変更:</span>
      <!-- ウォッチ リスナーを通じて実装できる基本データ型を変更する別の方法を示します -->
      <input type="text" v-model="dataMsg">
    </div>
  </div>
</テンプレート>

<スクリプト>
エクスポートデフォルト{
  名前: 'dataChild',
  小道具: {
    オブジェクト: {
      タイプ: オブジェクト、
      デフォルト: () => {}
    },
    メッセージ: {
      タイプ: 文字列、
      デフォルト: ''
    }
  },
  データ () {
    戻る {
      // 参照データ型が直接割り当てられると、それは浅いコピーとなり、メモリアドレスのみがコピーされ、一方を変更するともう一方に反映されます。dataObj: this.obj、
      // 基本データ型を直接割り当てると、値がコピーされ、一方を変更してももう一方には影響しません。dataMsg: this.msg
    }
  },
  時計:
    // ここでは、データからコピーされた dataMsg をリッスンし、変更されたら、emit を実行して親コンポーネントに dataMsg (newVal) を更新するように通知します。{
      this.$emit('update:msg', newVal)
    }
  }
}
</スクリプト>

4. 計算プロパティを通じてpropを変更する

前提条件: 参照データ型のみ実装可能

原理:

  • 子コンポーネントでは、親コンポーネントから渡された prop が、計算プロパティ computed を通じて直接リッスンされます。このとき、計算プロパティ computed と prop の両側の変数は同じメモリ アドレスを指しているため、計算プロパティ computed を変更することは prop を変更することと同じです。
  • Vue2 では props を直接変更することはできませんが、今回は prop ではなく計算プロパティ computed を変更しているため、Vue はエラーをスローしません。これは、props の変更を許可しない Vue の検出メカニズムをバイパスすることと同じです。

計算された

親コンポーネントのコードは次のとおりです。

<テンプレート>
  <div style="background-color: skyblue;">
    <h3>計算プロパティの監視を通じてプロパティを変更する</h3>
    <div>親オブジェクト:{{ obj }}</div>
    <div>親メッセージ:{{ メッセージ }}</div>
    <computedChild :obj="obj" :msg.sync="msg" />
  </div>
</テンプレート>

<スクリプト>
'./components/computedChild' から computedChild をインポートします。

エクスポートデフォルト{
  名前: 'computedUpdate',
  コンポーネント:
    計算された子
  },
  データ () {
    戻る {
      オブジェクト: {
        名前: 'zhangsan'、
        年齢: 18
      },
      メッセージ: 'こんにちは'
    }
  }
}
</スクリプト>

サブコンポーネントコードは次のとおりです。

<テンプレート>
  <div style="background-color: pink;">
    <div>
      <span>名前を変更:</span>
      <!-- ここでは、算出プロパティを通じて prop を直接リッスンしているので、v-model の双方向バインディングを直接使用してデータを変更できます -->
      <input type="text" v-model="computedObj.name">
    </div>
    <div>
      <span>年齢を変更:</span>
      <input type="text" v-model="computedObj.age">
    </div>
    <div>
      <span>メッセージを変更:</span>
      <!-- 基本データ型を変更する別の方法は、計算プロパティのセッターを通じて実現できます -->
      <input type="text" v-model="computedMsg">
    </div>
  </div>
</テンプレート>

<スクリプト>
エクスポートデフォルト{
  名前: 'computedChild',
  小道具: {
    オブジェクト: {
      タイプ: オブジェクト、
      デフォルト: () => {}
    },
    メッセージ: {
      タイプ: 文字列、
      デフォルト: ''
    }
  },
  計算: {
    計算されたオブジェクト() {
      // ここでは、参照データ型objが直接返されます。この時点で、computedObjはobjと同等です。
      // これは浅いコピーなので、メモリアドレスのみがコピーされ、一方を変更するともう一方に反映されます。 return this.obj
    },
    計算されたメッセージ: {
      得る () {
        // プロパティが更新されるたびに、計算プロパティのゲッターメソッドがトリガーされ、最新の値が取得されます // 基本データ型を直接返す場合、値がコピーされ、一方を変更してももう一方には影響しません。 return this.msg
      },
      設定(新しい値) {
        // ここでは、計算プロパティのセッターメソッドを使用して、値が変更されたときにエミットをトリガーし、親コンポーネントに値を更新するように通知します。this.$emit('update:msg', newVal)
      }
    }
  }
}
</スクリプト>

これで、子コンポーネントを介して親コンポーネントのプロパティを変更する Vue の実装方法に関するこの記事は終了です。親コンポーネントのプロパティを変更する Vue 子コンポーネントに関するより関連性の高いコンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、次の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Vueの子コンポーネントが親コンポーネントのメソッドを呼び出す場合の詳細な説明
  • Vue 親コンポーネントが子コンポーネント関数の実装を呼び出す
  • Vue で親コンポーネントから子コンポーネントにデータを渡すいくつかの方法
  • Vue の親コンポーネントのボタンをクリックして子コンポーネントをトリガーするイベントの詳細な説明
  • vueの子コンポーネントと親コンポーネント間で値を渡す例
  • Vue親コンポーネントは子コンポーネントのライフサイクルを監視します
  • Vue親コンポーネントはどのようにして子コンポーネントの変数を取得するのか
  • Vueの子コンポーネントと親コンポーネントの詳細な分析

<<:  MySQL における悲観的ロックと楽観的ロック

>>:  MySQL の自動増分 ID (主キー) が不足した場合の解決策

推薦する

Vue+Spring Bootで検証コード機能を実現

この記事では、検証コード機能を実装するためのvue+spring bootの具体的なコードを例として...

JavaScript の navigator.userAgent がブラウザ情報を取得するケースの説明

ブラウザはおそらく私たちにとって最も馴染みのあるツールです。 Firefox、Opera、Safar...

DIV、テーブル、XHTML のウェブサイト構築の違いの分析と説明

簡単に言えば、ウェブサイト構築とは、「この人はどんな外見をしているのか」と「この人はどんな内面を持っ...

タイムスタンプの差を計算するSQLメソッド

タイムスタンプの差を計算するSQLメソッド概要場合によっては、特定のレコードを時間で検索する必要があ...

停止したすべてのDockerコンテナを1つのコマンドで再起動する

停止したすべてのDockerコンテナを1つのコマンドで再起動するdocker ps -a | gre...

Ubuntuがインターネットに接続できない場合の解決策

問題の説明:デスクトップ コンピューターとキャンパス ネットワークを使用して、有線モードでインターネ...

ファイルが存在するかどうかを判断する JavaScript サンプルコード

1. ビジネスシナリオ最近はファイルのアップロードやダウンロードに関する開発をしています。ダウンロー...

複数の値を返す MySQL ストアド プロシージャ メソッドの例

この記事では、例を使用して、MySQL ストアド プロシージャで複数の値を返す方法について説明します...

Ubuntu 20.04 Firefox でビデオを再生できない (Flash プラグインがない) 場合の解決策

1. Flashプラグインパッケージのダウンロードアドレス: https://get.adobe.c...

MySQL インデックスの正しい使い方とインデックスの原理の詳細な説明

1. はじめになぜインデックスが必要なのでしょうか?一般的なアプリケーション システムでは、読み取り...

無効にするとフォームの入力が送信できない問題の解決方法

以前、追加と変更を一緒に記述したテストプログラムを書いたことがあります。変更が必要な場合は、フォーム...

JavaScript の for ループと二重 for ループの詳細な説明

forループfor ループは配列の要素をループします。文法: for (初期化変数; 条件式; 繰り...

ユニアプリプロジェクトでのウォーターフォールレイアウトの実装

GitHubアドレス、気に入ったらスターを付けてくださいプラグインのプレビューチュートリアル1. プ...

win2008 で mysql8.0.11 を mysql8.0.17 にアップグレードする詳細な手順

アップグレードの背景: MySQLの下位バージョンの脆弱性を解決するために、MySQLはMySQL ...

MySQLはストアドプロシージャを使用して数百万のデータを素早く追加します。サンプルコード

序文インデックスを追加した場合と追加しなかった場合の違いを反映するには、数百万のデータを使用する必要...