Vueコンポーネントが相互に値を転送する方法の詳細な説明

Vueコンポーネントが相互に値を転送する方法の詳細な説明

概要

Vue は軽量のフロントエンド フレームワークであり、その中核はコンポーネントベースの開発であることは誰もが知っています。 Vue はコンポーネントから構成されています。コンポーネント化は Vue の本質であり、最も強力な機能の 1 つです。コンポーネント インスタンスのスコープは互いに独立しているため、異なるコンポーネント間のデータは相互に参照できません。

しかし、実際のプロジェクト開発プロセスでは、他のコンポーネントのデータにアクセスする必要があるため、コンポーネント通信の問題が発生します。 Vue 内のコンポーネント間の関係は、父と子、兄弟、世代間の関係です。異なる関係でのデータ転送を実現する方法については、次に説明します。

1. 親コンポーネントが子コンポーネントに値を渡す

つまり、親コンポーネントは属性を通じて子コンポーネントに値を渡し、子コンポーネントは props を通じて値を受け取ります。

親コンポーネントの子コンポーネントタグにカスタムプロパティをバインドする

// 親コンポーネント <user-detail :myName="name" />
    
エクスポートデフォルト{
    コンポーネント:
        ユーザー詳細
    }
    ......
}

子コンポーネントでそれを受け取るには、props (配列またはオブジェクト) を使用します。複数の属性を渡すことが可能です。

// サブコンポーネントエクスポートデフォルト{
    プロパティ: ['myName']
}
​
/*
props: { myName: String } //この方法で渡される型を指定します。型が正しくない場合は警告が発行されます props: { myName: [String, Number] } // 複数の型が考えられます prosp: { myName: { type: String, requires: true } } //必須の文字列 props: { 
    子メッセージ: { 
        タイプ: 配列、 
        デフォルト: () => [] 
    }
} // default はデフォルト値を指定します。props の検証に失敗した場合は、コンソールに警告が表示されます。
*/

子コンポーネントが受け取る親コンポーネントの値は、参照型と共通型に分けられます。

一般的な型: 文字列、数値、ブール値、Null

参照型: 配列、オブジェクト

Vue の一方向データフローに基づいて、つまり、コンポーネント間のデータは一方向であり、子コンポーネントは親コンポーネントによって渡された値を直接変更することはできません。そのため、親コンポーネントによって渡された値を直接変更するこの操作は避ける必要があります。そうしないと、コンソールにエラーが報告されます。

渡された値が単純なデータ型の場合、親コンポーネントから値を呼び出す他の兄弟コンポーネントに影響を与えることなく、子コンポーネントで値を変更できます。

具体的な操作は、まず渡された値をデータ内の変数に再割り当てし、次にその変数を変更することです。

// サブコンポーネントエクスポートデフォルト{
    プロパティ: ['myName'],
    データ() {
        戻る {
            name : this.myName // 渡された値を新しい変数に代入します}
    },
    時計:
        myName(新しい値) {
            this.name = newVal //親コンポーネントから渡された値をリッスンし、変更された場合は子コンポーネント内の値も変更します}
    },
    メソッド: {
        名前を変更する() {  
            this.name = 'Lily' // ここでは内部値のみが変更されるため、エラーは報告されません},
    }
}

注: 親コンポーネントから渡される myName 値を監視するために watch を使用しない場合、データ内の name: this.myName は初期値のみを定義するため、子コンポーネントの name 値は親コンポーネントの myName 値によって変更されません。

子コンポーネントで参照型の値が変更されると、そのデータはパブリックであるため親コンポーネントも変更され、その値を参照する他の子コンポーネントも変更されます。親コンポーネントから子コンポーネントに渡される値はコピーを作成することと同等であり、このコピーのポインターは依然として親コンポーネント内のポインターを指している、つまり同じ参照を共有していることがわかります。したがって、特別な必要がない限り、簡単に変更しないでください。

2. 子コンポーネントが親コンポーネントに値を渡す

1. サブコンポーネントはイベントをバインドし、this.$emit() を通じてそれをトリガーします。

子コンポーネントにイベントをバインドし、このイベントの関数を定義します。

// 子コンポーネント <button @click="changeParentName">親コンポーネントの名前を変更する</button>
​
エクスポートデフォルト{
    メソッド: {
        //サブコンポーネントイベント changeParentName: function() {
            this.$emit('handleChange', 'Jack') // 親コンポーネントでhandleChangeイベントをトリガーし、それをJackに渡します
            // 注意: ここでのイベント名は、親コンポーネントにバインドされたイベント名と一致している必要があります}
    }
}

親コンポーネントでhandleChangeイベントを定義してバインドする

// 親コンポーネント <child @handleChange="changeName"></child>
​
メソッド: {
    changeName(name) { // nameパラメータは子コンポーネントJackから渡された値です
        this.name = 名前
    }
}

2. コールバック関数を通じて

まず親コンポーネントにコールバック関数を定義し、そのコールバック関数を渡します。

// 親コンポーネント <child :callback="callback"></child>
​
メソッド: {
    コールバック: 関数(名前) {
        this.name = 名前
    }
}

子コンポーネントで受信し、コールバック関数を実行する

// 子コンポーネント <button @click="callback('Jack')">親コンポーネントの名前を変更する</button>
​
小道具: {
    コールバック: 関数、
}

3. $parent / $children または $refs 経由でコンポーネントインスタンスにアクセスする

どちらのメソッドもコンポーネント インスタンスを直接取得し、使用後にコンポーネント メソッドを呼び出したり、データに直接アクセスしたりできます。

// サブコンポーネントエクスポートデフォルト{
  データ () {
    戻る {
      タイトル: 'サブコンポーネント'
    }
  },
  メソッド: {
    こんにちは(){
        console.log('こんにちは');
    }
  }
}
// 親コンポーネント <テンプレート>
  <childref="childRef" />
</テンプレート>
​
<スクリプト>
  エクスポートデフォルト{
    作成された(){
      // $ref を介して子コンポーネントにアクセスします console.log(this.$refs.childRef.title); // 子コンポーネント this.$refs.childRef.sayHello(); // Hello
      
      // $children を通じて子コンポーネントメソッドを呼び出す this.$children.sayHello(); // Hello 
    }
  }
</スクリプト>

注意: この方法でのコンポーネント通信はレベルを越えることはできません。

3. 兄弟コンポーネント間で値を転送する

1. $emitとpropsの組み合わせにより

親コンポーネントでは、2つの兄弟コンポーネントに渡される変数をバインドし、イベントを定義します。

// 親コンポーネント <child-a :myName="name" />
<child-b :myName="名前" @changeName="名前を編集" />  
    
エクスポートデフォルト{
    データ() {
        戻る {
            名前: 'ジョン'
        }
    },
    コンポーネント:
        'child-a': 子A、
        'child-b': 子B、
    },
    メソッド: {
        editName(名前) {
            this.name = 名前
        },
    }
}

子コンポーネントBで変数を受け取り、トリガーイベントをバインドする

// 子 b コンポーネント<p>名前: {{ myName }}</p>
<button @click="changeName">名前を変更</button>
    
<スクリプト>
エクスポートデフォルト{
    プロパティ: ["myName"],
    メソッド: {
        名前を変更する() {
            this.$emit('changeName', 'Lily') // イベントをトリガーして値を渡す}
    }
}
</スクリプト>
// 子コンポーネント<p>名前: {{ newName }}</p>
    
<スクリプト>
エクスポートデフォルト{
    プロパティ: ["myName"],
    計算: {
        新しい名前() {
            if(this.myName) { // 渡された値があるかどうかを確認します return this.myName
            }
            return 'John' //値が渡されない場合はデフォルト値}
    }
}
</スクリプト>

つまり、子コンポーネント B が $emit() を通じて親コンポーネントのイベント関数 editName をトリガーし、親コンポーネントの変数名の値を変更すると、親コンポーネントは props を通じて変更された値を子コンポーネント A に渡すことができ、兄弟コンポーネント間のデータ転送を実現できます。

2. 空のvueインスタンスを介して

EventBus.jsファイルを作成し、vueインスタンスを公開する

'Vue' から Vue をインポートします
デフォルトの新しい Vue() をエクスポートします

この空のvueインスタンスをファイルにインポートして値を渡し、イベントをバインドし、$emitを介してイベント関数をトリガーします。

(main.js で js ファイルをグローバルにインポートすることもできます。私は通常、使用する必要があるコンポーネントでインポートします。)

<テンプレート>
    <div>
        <p>名前: {{ name }}}</p>
        <button @click="changeName">名前を変更</button>
    </div>
</テンプレート>
​
<スクリプト>
「../EventBus.js」から{EventBus}をインポートします。
​
エクスポートデフォルト{
 データ() {
     戻る {
         名前: 'ジョン'、
     }
  },
  メソッド: {
      名前を変更する() {
          this.name = 'リリー'
          EventBus.$emit("editName", this.name) // グローバル イベントをトリガーし、変更された値をイベント関数に渡します}
    }
}
</スクリプト>

値を受け取るコンポーネントに vue インスタンスをインポートし、$on を介してコールバックをリッスンします。コールバック関数は、イベントがトリガーされたときに渡されるすべてのパラメーターを受け取ります。

「../EventBus.js」から{EventBus}をインポートします。
​
エクスポートデフォルト{
    データ() {
        戻る {
            名前: ''
        }
    },
    作成された() {
         EventBus.$on('editName', (名前) => {
             this.name = 名前
         })
    }
}

空の vue インスタンスを作成するこの方法は、イベントを送受信するためのイベント センターまたは交通機関の駅を作成するのと同じです。この方法は、親子、兄弟、クロスレベルなど、コンポーネント間のあらゆる通信にも適用できます。通信要件が単純なプロジェクトには便利ですが、より複雑な状況や大規模なプロジェクトの場合は、Vue が提供するより複雑な状態管理モード Vuex を使用して処理できます。

4. 多層親子コンポーネント通信

場合によっては、通信する必要がある 2 つのコンポーネントが直接の親子コンポーネントではなく、祖父と孫、または複数のレベルにまたがる親子コンポーネントであることがあります。この場合、子コンポーネントが一度に 1 レベルずつパラメータを上位に渡すことは不可能です。特に、コンポーネント階層が深く、ネストされたコンポーネントが多数ある場合は、渡す必要のあるイベントと属性が多くなり、コードが非常にわかりにくくなります。

このとき、Vue が提供するより高レベルのメソッドである provide/inject を使用する必要があります。

このオプションのペアは、コンポーネント階層の深さに関係なく、祖先コンポーネントがそのすべての子孫に依存関係を注入できるようにするために一緒に使用する必要があります。また、上流と下流の関係が維持されている限り常に機能します。

提供/注入: 簡単に言うと、変数は親コンポーネントのプロバイダーを通じて提供され、その後、注入を通じて子コンポーネントに注入されます。コンポーネント階層の深さに関係なく、変数は親コンポーネントのライフサイクル中は常に有効です。

親コンポーネント:

エクスポートデフォルト{
  provide: { // その機能は、変数 **name** をすべての子コンポーネントに提供することです。
    名前: 'ジャック'
  }
}

サブコンポーネント:

エクスポートデフォルト{
  inject: ['name'], // 親コンポーネントによって提供される名前変数を注入します。mounted() {
    console.log(this.name); // ジャック
  }
}

注意: provide および inject バインディングはリアクティブではありません。つまり、親コンポーネントの名前が変更されても、子コンポーネントはそれに応じて変更されません。

データ応答を提供して挿入する場合、次の 2 つの方法があります。

祖先コンポーネントのインスタンスを用意し、子孫コンポーネントに依存関係を注入することで、祖先コンポーネントインスタンスのプロパティを子孫コンポーネントで直接変更できるようになります。ただし、この方法には、このインスタンスに props やメソッドなど不要なものが多くマウントされるという欠点があります。

// 親コンポーネント <div>
      <button @click="changeName">名前を変更</button>
      <子-b />
</div>
<スクリプト>
    ......
    データ() {
        戻る {
            名前: 「ジャック」
        };
    },
    提供する() {
        戻る {
            parentObj: this // 祖先コンポーネントのインスタンスを提供する};
    },
    メソッド: {
        名前を変更する() {
            this.name = 'リリー'
        }
    }
</スクリプト>

子孫コンポーネントの値:

<テンプレート>
  <div class="border2">
    <P>名前: {{parentObj.name}}</P>
  </div>
</テンプレート>
<スクリプト>
  エクスポートデフォルト{
    注入: {
      親オブジェクト: {
        デフォルト: () => ({})
      }
    } // または inject: ['parentObj']
  };
</スクリプト>

注: このメソッドは、機能コンポーネントでよく使用されます。機能コンポーネントは、ステートレス(応答データなし)、インスタンス化なし(this コンテキストなし)、内部にライフサイクル処理メソッドがありません。そのため、レンダリング パフォーマンスが高く、外部データ転送に依存するコンポーネントに適しています。

要約する

親子間の通信: 親は props を通じて子にデータを渡し、子は $emit を通じて親にデータを渡します。$parent / $children を通じて通信します。$ref はコンポーネント インスタンスにもアクセスできます。$attrs / $listeners を提供/注入します。

兄弟通信: EventBus; Vuex;

クロスレベル通信: EventBus、Vuex、provide / inject、$attrs / $listeners、

以上が、Vue コンポーネント同士がどのように値を渡すのかの詳しい説明です。Vue についてさらに詳しく知りたい方は、123WORDPRESS.COM 内の他の関連記事もぜひご注目ください!

以下もご興味があるかもしれません:
  • Vue で 2 つのコンポーネント間で値を転送または変更する方法
  • 値の転送を実現するために、2つの同じレベルのコンポーネントをVueで作成します。
  • Vue コンポーネント間で値を渡す方法をどうやって知っていますか?
  • Vueはストアを使用して2つの並列コンポーネント間で値を転送する方法

<<:  Linux の運用と保守で netstat の代わりに ss コマンドを使用する方法

>>:  今日と昨日の 0:00 タイムスタンプを取得する MySQL の例

推薦する

LinuxサーバーにVueプロジェクトをデプロイする

ケース1 vue-cliはvue3プロジェクトをビルドし、プロジェクトをLinuxサーバーにアップロ...

シンプルな画像切り替えを実現するJavaScript

この記事では、JavaScriptで簡単な画像切り替えを実現するための具体的なコードを参考までに紹介...

画像ファイルの形式とその選択方法

1. どの 3 つの形式ですか?それぞれ、gif、jpg、png です。画像ファイルを最適化すること...

浮遊する雲のアニメーションを実現するCSS3

操作効果 html <ヘッド> <メタ文字セット='UTF-8'&...

MySQL で準備、実行、割り当て解除ステートメントを使用するチュートリアル

序文MySQLでは、準備、実行、割り当て解除を正式にはPREPARE STATEMENTと呼びます。...

Reactの状態の理解についての簡単な分析

複雑なコンポーネント (クラス コンポーネント) と単純なコンポーネント (関数コンポーネント) を...

LinuxシステムにTomcatをインストールし、サービスの起動とシャットダウンを構成する

Linuxシステムでサービスの起動とシャットダウンを構成する1. コマンドcd /etc/init....

MySQL スロークエリログの基本的な使い方チュートリアル

スロークエリログ関連のパラメータMySQL スロー クエリ関連のパラメータの説明: slow_que...

Zabbix redis 自動ポート検出スクリプトは json 形式を返します

自動検出を行う際には、ポートなどの情報を取得してjson形式で返すスクリプトが必ず存在します。Red...

HTML フォームタグチュートリアル (5): テキストフィールドタグ

<br />このタグは、さらにテキストを入力できる複数行のテキスト フィールドを作成する...

vmware workstation12 インストール CentOS プロンプト VMware Player と Device/Credential Guard に互換性がない、理由と解決策

最新バージョンの WIN10 では、Microsoft は仮想化コンテナに基づくセキュリティ メカニ...

MySQL バイナリログデータ復旧: 誤ってデータベースを削除した場合の詳細な説明

MySQL Binログデータの回復: 誤ってデータベースを削除した場合前書き: テスト マシンで誤っ...

派手なカルーセル効果を実現するJavaScript

この記事では、JavaScriptで派手なカルーセル効果を実装する2つの方法を紹介します。具体的な内...

HTML ページをスクロールするときに一部のコンテンツを固定位置に固定する方法

この記事では主に、レイアウトに役立つ、HTML ページ内の一部のコンテンツを固定してスクロール時にス...

ウェブページで CSS スタイルを適用するさまざまな形式の概要

1. インライン スタイル (<body></body> 内に配置されます)...