vue.jsのコンポーネントにデータを渡す


92

vue.jsのコンポーネント間でデータを渡す方法を理解するのに苦労しています。ドキュメントを数回読み、vueに関連する多くの質問やチュートリアルを確認しましたが、まだ理解できていません。

これに頭を悩ませるために、私は非常に単純な例を完成させる助けを望んでいます

  1. 1つのコンポーネントにユーザーのリストを表示する(完了)
  2. リンクがクリックされた(完了した)ときに、ユーザーデータを新しいコンポーネントに送信します-下部の更新を参照してください。
  3. ユーザーデータを編集して、元のコンポーネントに送り返します(ここまで取得していません)

これがステップ2で失敗するフィドルです:https//jsfiddle.net/retrogradeMT/d1a8hps0/

新しいコンポーネントにデータを渡すために小道具を使用する必要があることは理解していますが、機能的にそれを行う方法がわかりません。データを新しいコンポーネントにバインドするにはどうすればよいですか?

HTML:

    <div id="page-content">
       <router-view></router-view>
     </div>

 <template id="userBlock" >
   <ul>
     <li v-for="user in users">{{user.name}} - <a v-link="{ path: '/new' }"> Show new component</a>
     </li>
   </ul>
 </template>

  <template id="newtemp" :name ="{{user.name}}">
    <form>
      <label>Name: </label><input v-model="name">
      <input type="submit" value="Submit">
    </form>
  </template>

主要コンポーネントのjs:

Vue.component('app-page', {
  template: '#userBlock',

  data: function() {
    return{

        users: []
      }
    },

ready: function () {
    this.fetchUsers();
},

methods: {
    fetchUsers: function(){
        var users = [
          {
            id: 1,
            name: 'tom'
          },
          {
            id: 2,
            name: 'brian'
          },
          {
            id: 3,
            name: 'sam'
          },
        ];

        this.$set('users', users);
     }
    }
  })

2番目のコンポーネントのJS:

Vue.component('newtemp', {
  template: '#newtemp',
  props: 'name',
  data: function() {
    return {
        name: name,
        }
   },
})

更新

わかりました、私は2番目のステップを理解しました。これが進捗状況を示す新しいフィドルです:https//jsfiddle.net/retrogradeMT/9pffnmjp/

私はVue-routerを使用しているので、データを新しいコンポーネントに送信するために小道具を使用しません。代わりに、v-linkにパラメータを設定し、遷移フックを使用してそれを受け入れる必要があります。

Vリンクの変更は、vue-routerドキュメントの名前付きルートを参照してください

<a v-link="{ name: 'new', params: { name: user.name }}"> Show new component</a>

次に、コンポーネントで、ルートオプションにデータを追加します。遷移フックを参照してください

Vue.component('newtemp', {
  template: '#newtemp',
  route: {
   data: function(transition) {
        transition.next({
            // saving the id which is passed in url
            name: transition.to.params.name
        });
     }
  },
 data: function() {
    return {
        name:name,
        }
   },
})

回答:


46

-------------以下はVue1にのみ適用されます--------------

データの受け渡しは、複数の方法で実行できます。方法は使用の種類によって異なります。


新しいコンポーネントを追加するときにHTMLからデータを渡したい場合。それは小道具を使用して行われます。

<my-component prop-name="value"></my-component>

この小道具の値はprop-nameprops属性に小道具名を追加した場合にのみコンポーネントで使用できます。


動的または静的なイベントが原因で、データがコンポーネントから別のコンポーネントに渡される場合。これは、イベントディスパッチャーとブロードキャスターを使用して行われます。したがって、たとえば、次のようなコンポーネント構造がある場合:

<my-parent>
    <my-child-A></my-child-A>
    <my-child-B></my-child-B>
</my-parent>

そして<my-child-A><my-child-B>それからデータを送信したい<my-child-A>場合は、イベントをディスパッチする必要があります。

this.$dispatch('event_name', data);

このイベントは、親チェーンのずっと上を移動します。そして、あなたがあなたに向かってブランチを持っている親から<my-child-B>、データと一緒にイベントをブロードキャストします。したがって、親では:

events:{
    'event_name' : function(data){
        this.$broadcast('event_name', data);
    },

これで、このブロードキャストは子チェーンを下って移動します。そして、イベントを取得したい子に、この場合<my-child-B>は別のイベントを追加します。

events: {
    'event_name' : function(data){
        // Your code. 
    },
},

データを渡す3番目の方法は、vリンクのパラメーターを使用することです。このメソッドは、コンポーネントチェーンが完全に破棄された場合、またはURIが変更された場合に使用されます。そして、私はあなたがすでにそれらを理解しているのを見ることができます。


必要なデータ通信の種類を決定し、適切に選択します。


1
ありがとう、それは本当に役に立ちました。私がまだ苦労している唯一の部分は、命名規則です。つまり、v-linkを介して名前として渡すuser.nameがあります。これで、name変数を編集して、nameとして元のコンポーネントに戻すことができますが、元のコンポーネントにはnameという変数がありません。ここで何が欠けていますか?v-linkを介してオブジェクトを渡すことができないように見えますか?
逆行2015

1
すでにオブジェクトを渡しています。paramsオブジェクトです。名前キーはthis.user.name、コンポーネントで割り当てることができます。ヘルプが必要な場合はフィドルを作成し、私に知らせてください。これをチェックしてください:vuejs.github.io/vue-router/en/route.html
notANerdDev

ああ、わかりました、私は今それを持っています。再度、感謝します。私はあなたの助けに感謝します、それは本当に物事をはるかに明確にしました。
逆行2016年

6
素晴らしい答えですが、イベントが非推奨になっているため、2.0では機能しないことを理解していますか?
rix 2016年

2
私は答えが好きでしたが、コメントにたどり着きました。Vue2を使用しているので、あなたが提案した2番目の方法は使用できないと感じています。それは正しく恐れられていますか?
Konrad Viltersten 2016

23

親コンポーネントから子にデータを送信する最良の方法は、小道具を使用することです。

を介して親から子にデータを渡す props

  • 子でprops(配列またはオブジェクト)を宣言します
  • 経由で子供に渡す <child :name="variableOnParent">

以下のデモを参照してください。

Vue.component('child-comp', {
  props: ['message'], // declare the props
  template: '<p>At child-comp, using props in the template: {{ message }}</p>',
  mounted: function () {
    console.log('The props are also available in JS:', this.message);
  }
})

new Vue({
  el: '#app',
  data: {
    variableAtParent: 'DATA FROM PARENT!'
  }
})
<script src="https://unpkg.com/vue@2.5.13/dist/vue.min.js"></script>

<div id="app">
  <p>At Parent: {{ variableAtParent }}<br>And is reactive (edit it) <input v-model="variableAtParent"></p>
  <child-comp :message="variableAtParent"></child-comp>
</div>


小さな修正: "<子-COMP"の代わりに"<子"とvariableAtParentが.. <子-COMPを経由して子に渡します。name = "variableAtParent">
muenalan

単純なプロパティでのみ機能し、オブジェクト参照は更新されません。たとえば、親プロパティが配列であり、この配列が親オブジェクトで別の配列に置き換えられた場合、子には表示されません。
スタンソコロフ

@StanSokolovはまったくありません。私は配列に対して機能します。jsfiddle.net / acdcjunior / q4mank05を参照してください。アレイが反応性でない場合は、反応性の問題に直面している可能性があります。Vue.set詳細はこちらを使用してみてください:vuejs.org/v2/guide/reactivity.html#For-Arrays
acdcjunior

反応性がない場合はどうなりますか?確かに、参照は常に新しいアレイに置き換えられて反応しました。Vueは「参照の変更」を子に伝播せず、単純な要素の値の変更のみを伝播します。したがって、配列への参照が親で上書きされた場合でも、子には古い参照が表示されます。親が別のオブジェクトで動作するようになったことがわかりません。
スタンソコロフ

@StanSokolovこれを参照してください:jsfiddle.net/acdcjunior/ftmrne2h配列は親で置き換えられ、子はそれを見て/反応します(テストするにはボタンをクリックしてください)。それとも何か他の意味ですか?もしそうなら、あなたがそれを示すためにフィドルを編集するならば、それは役に立ちます
acdcjunior

15

問題はここにあると思います:

<template id="newtemp" :name ="{{user.name}}">

小道具の前にあなたを付けると、:それが文字列ではなく変数であることをVueに示します。だからあなたは{{}}周りを必要としませんuser.name。試してみてください:

<template id="newtemp" :name ="user.name">

編集-----

上記は真実ですが、ここでのより大きな問題は、URLを変更して新しいルートに移動すると、元のコンポーネントが消えることです。2番目のコンポーネントで親データを編集するには、2番目のコンポーネントが最初のコンポーネントの子コンポーネントであるか、同じコンポーネントの一部である必要があります。


ありがとうジェフ。{{}}を削除しようとしましたが、それでも同じエラーが発生します。
逆行

2

Vueのコンポーネントスコープに親データを渡す方法を見つけました。少しハックだと思いますが、これが役立つかもしれません。

1)外部オブジェクトとしてのVueインスタンスの参照データ (data : dataObj)

2)次に、子コンポーネントのデータ戻り関数で、returnparentScope = dataObjとvoilaを実行します。今、あなたはそのようなこと{{ parentScope.prop }}をすることができず、魅力のように働くでしょう。

幸運を!


これは、両方のコンポーネントを結合して、ツリーとそのノードにとって問題がないことを示しますが、通常は好ましくありません。私はこれを避けようとします。
2018年

1

上記の応答はうまく機能しますが、2つの兄弟コンポーネント間でデータを渡したい場合は、イベントバスを使用することもできます。あなたがよりよく理解するのを助けるであろうこのブログをチェックしてください。

2つのコンポーネントを想定します:メインvueアプリをセットアップするために同じ親とmain.jsを持つCompAとCompB。親コンポーネントを使用せずにCompAからCompBにデータを渡すには、次のようにします。

main.jsファイルで、イベントバスとなる別のグローバルVueインスタンスを宣言します。

export const bus = new Vue();

イベントが生成されるCompAでは、イベントをバスに送信する必要があります。

methods: {
      somethingHappened (){
          bus.$emit('changedSomething', 'new data');
      }
  }

ここでのタスクは、発行されたイベントをリッスンすることです。したがって、CompBでは、のようにリッスンできます。

created (){
    bus.$on('changedSomething', (newData) => {
      console.log(newData);
    })
  }

利点:

  • 少ない&クリーンなコード。
  • 親は、ある子コンプから別の子コンプにデータを渡すことに関与すべきではありません(子の数が増えると、維持するのが難しくなります)
  • pub-subアプローチに従います。

0

を使用してメインプロパティにアクセスします$root

Vue.component("example", { 
    template: `<div>$root.message</div>`
});
...
<example></example>

-2

グローバルJS変数(オブジェクト)を使用して、コンポーネント間でデータを渡すことができます。例:Ammlogin.vueからOptions.vueにデータを渡す。Ammlogin.vueでは、rspDataはサーバーからの応答に設定されます。Options.vueでは、サーバーからの応答がrspDataを介して利用可能になります。

index.html:

<script>
    var rspData; // global - transfer data between components
</script>

Ammlogin.vue:

....    
export default {
data: function() {return vueData}, 
methods: {
    login: function(event){
        event.preventDefault(); // otherwise the page is submitted...
        vueData.errortxt = "";
        axios.post('http://vueamm...../actions.php', { action: this.$data.action, user: this.$data.user, password: this.$data.password})
            .then(function (response) {
                vueData.user = '';
                vueData.password = '';
                // activate v-link via JS click...
                // JSON.parse is not needed because it is already an object
                if (response.data.result === "ok") {
                    rspData = response.data; // set global rspData
                    document.getElementById("loginid").click();
                } else {
                    vueData.errortxt = "Felaktig avändare eller lösenord!"
                }
            })
            .catch(function (error) {
                // Wu oh! Something went wrong
                vueData.errortxt = error.message;
            });
    },
....

Options.vue:

<template>
<main-layout>
  <p>Alternativ</p>
  <p>Resultat: {{rspData.result}}</p>
  <p>Meddelande: {{rspData.data}}</p>
  <v-link href='/'>Logga ut</v-link>
</main-layout>
</template>
<script>
 import MainLayout from '../layouts/Main.vue'
 import VLink from '../components/VLink.vue'
 var optData = { rspData: rspData}; // rspData is global
 export default {
   data: function() {return optData},
   components: {
     MainLayout,
     VLink
   }
 }
</script>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.