Vue.jsコンポーネント-カスタムイベント

親コンポーネントはpropsでデータを子コンポーネントに渡しますが、子コンポーネントがデータを返す場合は、カスタムイベントを使用する必要があります。

v-onを使用して、カスタムイベントをバインドできます。各Vueインスタンスは、イベントインターフェイス(Events interface)を実装します。

  • $on(eventName)でイベントをリッスンします
  • $emit(eventName)でイベントをトリガーします

さらに、親コンポーネントは子コンポーネントが使用されているところにv-onを直接使用して、子コンポーネントによってトリガーされたイベントをリッスンできます。

次の例では、子コンポーネントはその外部から完全に切り離されています。 親コンポーネントにある内部イベントをトリガーするだけです。

<div id="app">
	<div id="counter-event-example">
	  <p>{{ total }}</p>
	  <button-counter v-on:increment="incrementTotal"></button-counter>
	  <button-counter v-on:increment="incrementTotal"></button-counter>
	</div>
</div>

<script>
Vue.component('button-counter', {
  template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    incrementHandler: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})
new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})
</script>

コンポーネントのルート要素でネイティブイベントをリッスンする場合、.nativeを使用してv-onを改善できます。 例えば:

<my-component v-on:click.native="doTheThing"></my-component>

dataは関数でなければなりません。

上記の例から見ると、button-counterコンポーネントのdataがオブジェクトではなく、関数です。

data: function () {
  return {
    count: 0
  }
}

メリットは、各インスタンスが返されたオブジェクトの独立したコピーを維持できることです。dataがオブジェクトの場合、次の例が示すように、他のインスタンスが影響を受けます。

<div id="components-demo3" class="demo">
    <button-counter2></button-counter2>
    <button-counter2></button-counter2>
	<button-counter2></button-counter2>
</div>

<script>
var buttonCounter2Data = {
  count: 0
}
Vue.component('button-counter2', {
    /*
    data: function () {
	    // dataオプションは関数の場合、コンポーネントは相互に影響を与えない
        return {
            count: 0
        }
    },
    */
    data: function () {
        // dataがオブジェクトの場合、他のインスタンスが影響を受ける
        return buttonCounter2Data
    },
    template: '<button v-on:click="count++"> {{ count }} 回にクリックされた。</button>'
})
new Vue({ el: '#components-demo3' })
</script>

カスタムコンポーネントのv-model

コンポーネントのv-modelは、デフォルトでvalueという名前のpropとinputという名前のイベントを使用します。

<input v-model="parentData">

<input 
    :value="parentData"
    @input="parentData = $event.target.value"
>

と同じです。

次のカスタムコンポーネントrunoob-inputの例では、親コンポーネントのnumの初期値は100です。子コンポーネントの値を変更すると、親コンポーネントのnumをリアルタイムで更新できます。

<div id="app">
    <runoob-input v-model="num"></runoob-input>
    <p>入力された数値:{{num}}</p>
</div>
<script>
Vue.component('runoob-input', {
    template: `
    <p>   <!-- inputという名前のイベントが含む -->
      <input
       ref="input"
       :value="value" 
       @input="$emit('input', $event.target.value)"
      >
    </p>
    `,
    props: ['value'], // valueというprop
})
   
new Vue({
    el: '#app',
    data: {
        num: 100,
    }
})
</script>

v-modelはデフォルトでvalueを渡し、checkedではないため、単一のチェックボックスまたは複数のチェックボックスコンポーネントにmodelオプションを使用する必要があります。modelオプションは、現在のイベントのタイプと導入されたpropsを指定できます。

<div id="app">
    <base-checkbox v-model="lovingVue"></base-checkbox> 
     <div v-show="lovingVue"> 
        チェックボックスがオンの場合は表示する。 
    </div>
</div> 
<script>
// 登録
Vue.component('base-checkbox', {
 
  model: {
    prop: 'checked',
    event: 'change'  // onchange イベント
  },
  props: {
    checked: Boolean
  },
   
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})
// ルートVueインスタンスを作成する
new Vue({
  el: '#app',
  data: {
    lovingVue: true
  }
})
</script>

この例では、lovingVueの値がcheckedのpropに渡され、changeイベントがによってトリガーされると、lovingVueの値も更新されます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です