web-dev-qa-db-ja.com

親イベントで子コンポーネントのfunctionを呼び出す方法

コンテキスト

Vue 2.0では、ドキュメンテーションと その他 は、親から子へのコミュニケーションが小道具を介して行われることを明確に示しています。

質問

親は自分の子供に小道具を使ってイベントが発生したことをどのように伝えますか?

イベントと呼ばれる小道具を見るだけでいいのでしょうか。それは正しいとは思えないし、代替策もありません($emit/$onは子供から親へ、ハブモデルは遠方の要素用です)。

私は親コンテナを持っています、そしてそれはその子コンテナにそれがそれがAPIの特定の行動を従事させても大丈夫であることを伝える必要があります。 関数を起動できるようにする必要があります。

87
jbodily

子コンポーネントにrefを指定し、$refsを使用して子コンポーネントのメソッドを直接呼び出します。

html:

<div id="app">
  <child-component ref="childComponent"></child-component>
  <button @click="click">Click</button>  
</div>

javaScript:

var ChildComponent = {
  template: '<div>{{value}}</div>',
  data: function () {
    return {
      value: 0
    };
  },
  methods: {
    setValue: function(value) {
        this.value = value;
    }
  }
}

new Vue({
  el: '#app',
  components: {
    'child-component': ChildComponent
  },
  methods: {
    click: function() {
        this.$refs.childComponent.setValue(2.0);
    }
  }
})

詳しくは、 参照に関するVueのドキュメント をご覧ください。

117
joerick

あなたが説明しているのは、親の状態の変化です。あなたはそれを小道具を通して子供に渡します。あなたが示唆したように、あなたはその小道具をwatchするでしょう。子供が行動をとるとき、それはemitを介して親に通知し、そして親は再び状態を変更するかもしれません。

var Child = {
  template: '<div>{{counter}}</div>',
  props: ['canI'],
  data: function () {
    return {
      counter: 0
    };
  },
  watch: {
    canI: function () {
      if (this.canI) {
        ++this.counter;
        this.$emit('increment');
      }
    }
  }
}
new Vue({
  el: '#app',
  components: {
    'my-component': Child
  },
  data: {
    childState: false
  },
  methods: {
    permitChild: function () {
      this.childState = true;
    },
    lockChild: function () {
      this.childState = false;
    }
  }
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<div id="app">
<my-component :can-I="childState" v-on:increment="lockChild"></my-component>
<button @click="permitChild">Go</button>
</div>

本当に子供にイベントを渡したい場合は、 バスを作成し(それは単なるVueインスタンスです)、それを小道具として子供に渡します

50
Roy J

$emit$onを使うことができます。 @ RoyJコードを使う:

html:

<div id="app">
  <my-component></my-component>
  <button @click="click">Click</button>  
</div>

javaScript:

var Child = {
  template: '<div>{{value}}</div>',
  data: function () {
    return {
      value: 0
    };
  },
  methods: {
    setValue: function(value) {
        this.value = value;
    }
  },
  created: function() {
    this.$parent.$on('update', this.setValue);
  }
}

new Vue({
  el: '#app',
  components: {
    'my-component': Child
  },
  methods: {
    click: function() {
        this.$emit('update', 7);
    }
  }
})

実行例: https://jsfiddle.net/rjurado/m2spy60r/1/

24
drinor

時間がある場合は、Vuexストアを使用して変数を監視する(別名状態)か、アクションを直接トリガーする(別名ディスパッチ)。

5
brightknight08

子コンポーネントのメソッドを呼び出す簡単な方法は、子からハンドラを発行してから親からそれを呼び出すことです。

var Child = {
  template: '<div>{{value}}</div>',
  data: function () {
    return {
      value: 0
    };
  },
  methods: {
        setValue(value) {
        this.value = value;
    }
  },
  created() {
    this.$emit('handler', this.setValue);
  }
}

new Vue({
  el: '#app',
  components: {
    'my-component': Child
  },
  methods: {
        setValueHandler(fn) {
        this.setter = fn
    },
    click() {
        this.setter(70)
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>

<div id="app">
  <my-component @handler="setValueHandler"></my-component>
  <button @click="click">Click</button>  
</div>

親は子ハンドラ関数を追跡し、必要に応じて呼び出します。

2
nilobarp

次の例は自明です。refとイベントを使用して、親と子の間で関数を呼び出すことができます。

// PARENT
<template>
  <parent>
    <child
      @onChange="childCallBack"
      ref="childRef"
      :data="moduleData"
    />
    <button @click="callChild">Call Method in child</button>
  </parent>
</template>

<script>
export default {
  methods: {
    callChild() {
      this.$refs.childRef.childMethod('Hi from parent');
    },
    childCallBack(message) {
      console.log('message from child', message);
    }
  }
};
</script>

// CHILD
<template>
  <child>
    <button @click="callParent">Call Parent</button>
  </child>
</template>

<script>
export default {
  methods: {
    callParent() {
      this.$emit('onChange', 'hi from child');
    },
    childMethod(message) {
      console.log('message from parent', message);
    }
  }
}
</script>
2
Mukundhan

createの間に子で$onバインディングを使用する イベントバスアプローチ が気に入らなかった。どうして?後続のcreate呼び出し(私はvue-routerを使用しています)はメッセージハンドラを複数回バインドします - メッセージごとに複数の応答が発生します。

親から子に小道具を渡し、子にプロパティウォッチャーを置くという正統的な解決策は、少しよく機能しました。唯一の問題は、子供が価値の変化にしか行動できないということです。同じメッセージを何度も渡すと、子供が変更を認識できるように移行を強制するためにある種の簿記が必要です。

メッセージを配列でラップすると、値が同じままであっても、子ウォッチャーが常にトリガーされることがわかりました。

親:

{
   data: function() {
      msgChild: null,
   },
   methods: {
      mMessageDoIt: function() {
         this.msgChild = ['doIt'];
      }
   }   
   ...
}

子:

{
   props: ['msgChild'],
   watch: {
      'msgChild': function(arMsg) {
         console.log(arMsg[0]);
      }
   }
}

HTML:

<parent>
   <child v-bind="{ 'msgChild': msgChild }"></child>
</parent>
1
Jason Stewart

ミックスインを使用して共有データ属性を設定できます。親の中でそれを変更し、子の中でそれを見てください。

// mixin
export default {
  data() {
    return  {
      clicked: false
    }
  }
}

// parent
export default {
  mixins: [myMixin],
  methods: {
    btnClick() {
      this.clicked = true
    }
  }
}

// child
export default {
  mixins: [myMixin],
  watch: {
    clicked(val) {
      if(val) {
        // yay
      }
    }
  }
}
0
digout

実際には、親は子のメソッドに関係する必要はありませんが、子コンポーネントをFSA(Finite State Machine)として扱うことができます。親コンポーネント子コンポーネントの状態を制御します。状態の変化を監視するか、単にcompute関数を使用するだけで十分です。

0
user10097040