カスタムイベント
このページは、コンポーネントの基本を読んでいることを前提としています。コンポーネントについてまだよく知らない場合は、最初に読むことをお勧めします。
ディレクトリ
## イベント名
#コンポーネントやプロップとは異なり、イベント名には自動大文字小文字変換がありません。代わりに、トリガーされたイベントの名前は、このイベントをリッスンするために使用される名前と正確に一致する必要があります。たとえば、キャメルケース名を持つイベントがトリガーされた場合: this.$emit('myEvent')
、この名前のケバブケース バージョンをリッスンしても効果はありません:
<!-- 没有效果 --> <my-component v-on:my-event="doSomething"></my-component>
コンポーネントやプロップとは異なり、イベントはこの名前は JavaScript 変数またはプロパティ名として使用されないため、キャメルケースやパスカルケースを使用する理由はありません。また、
v-on
イベント リスナーは DOM テンプレート内で自動的にすべて小文字に変換されるため (HTML では大文字と小文字が区別されないため)、v-on:myEvent
は ## になります。 #v-on:myevent——myEvent
を監視できなくなります。 したがって、
常に
kebab-case イベント名
を使用することをお勧めします。
# カスタム コンポーネントの
## 2.2.0 コンポーネントに
v-modelを追加しました。デフォルトでは、
valueイベントですが、ラジオ ボタンやチェック ボックスなどの入力コントロールは、という名前のプロップと
input という名前のプロップが使用されます。
別の目的で value
属性を使用する場合があります。 model
オプションを使用すると、このような競合を回避できます:
Now when using Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
v-model
on thisコンポーネント: <base-checkbox v-model="lovingVue"></base-checkbox>
here 値lovingVue
は、
という名前のこのプロップに渡されます。同時に、<base-checkbox>
が新しい値で
イベントをトリガーすると、lovingVue
プロパティが更新されます。 このプロップをコンポーネントの
props オプションで
checked 宣言する必要があることに注意してください。
#ネイティブ イベントをコンポーネントにバインドする
今回は多数ある可能性があります。コンポーネントのルート要素でネイティブ イベントを直接リッスンしたいと考えています。現時点では、
の .native 修飾子を使用できます: <base-input v-on:focus.native="onFocus"></base-input>
これは便利な場合もありますが、<input>
のような非常に特定の要素をリッスンしようとしている場合にはお勧めできません。たとえば、上記の <base-input>
コンポーネントは次のようにリファクタリングできるため、ルート要素は実際には <label>
要素になります:
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
現時点では、親の .native
リスナーはサイレントに失敗します。エラーは生成されませんが、onFocus
ハンドラーは期待どおりに呼び出されません。
この問題を解決するために、Vue は $listeners
プロパティを提供します。これは、このコンポーネントで動作するすべてのリスナーを含むオブジェクトです。例:
{
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}
この $listeners
属性では、v-on="$listeners"
を使用して、すべてのイベント リスナーがこのコンポーネントを指すようにすることができます。子要素。 v-model
とも連携したい <input>
のようなコンポーネントの場合、次のようなリスナーを作成します。 inputListeners
の計算されたプロパティが正確に使用されます。通常の
<input> 要素と同様に、すべて同じ属性とリスナーが機能します。
#.sync
修飾子
2.3.0 New場合によっては、プロップに対して「双方向バインディング」を実行する必要があるかもしれません。残念ながら、真の双方向バインディングでは、親コンポーネントにも子コンポーネントにも明らかな変更源がなくても、子コンポーネントが親コンポーネントを変更できるため、メンテナンスの問題が発生します。
これが、代わりに update:myPropName モードを使用してイベントをトリガーすることをお勧めする理由です。たとえば、
title
プロップを含む仮想コンポーネントでは、次のようにしてそれに新しい値を割り当てる意図を表現できます。 Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
computed: {
inputListeners: function () {
var vm = this
// `Object.assign` 将所有的对象合并为一个新对象
return Object.assign({},
// 我们从父级添加所有的监听器
this.$listeners,
// 然后我们添加自定义监听器,
// 或覆写一些监听器的行为
{
// 这里确保组件配合 `v-model` 的工作
input: function (event) {
vm.$emit('input', event.target.value)
}
}
)
}
},
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on="inputListeners"
>
</label>
`
})
その後、親コンポーネントはそのイベントをリッスンし、必要に応じてローカル データ属性を更新します。例: this.$emit('update:title', newTitle)
便宜上、このモードの略語を
.sync とします。修飾子:
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
が付いた文字に注意してください。 .sync 修飾子 v-bind
は、式 (例: v-bind:title.sync="doc.title '!'# #) では使用できません。 #"は無効です)。代わりに、バインドするプロパティの名前 (v-model など) のみを指定できます。
オブジェクトを使用して複数のプロパティを同時に設定する場合、この .sync 修飾子を v-bind
とともに使用することもできます: <text-document v-bind:title.sync="doc.title"></text-document>
これにより、doc オブジェクトの各属性 (タイトルなど) が独立した prop として渡され、更新用の v-on リスナーが追加されます。
リテラル オブジェクトで v-bind.sync
を使用します。たとえば、v-bind.sync=”{ title: doc.title }”
、このような複雑な式を解析する際には考慮すべきエッジケースが多数あるため、正しく動作しません。
<input>
のような非常に特定の要素をリッスンしようとしている場合にはお勧めできません。たとえば、上記の <base-input>
コンポーネントは次のようにリファクタリングできるため、ルート要素は実際には <label>
要素になります: .native
リスナーはサイレントに失敗します。エラーは生成されませんが、onFocus
ハンドラーは期待どおりに呼び出されません。 $listeners
プロパティを提供します。これは、このコンポーネントで動作するすべてのリスナーを含むオブジェクトです。例: $listeners
属性では、v-on="$listeners"
を使用して、すべてのイベント リスナーがこのコンポーネントを指すようにすることができます。子要素。 v-model
とも連携したい <input>
のようなコンポーネントの場合、次のようなリスナーを作成します。 inputListeners
の計算されたプロパティが正確に使用されます。通常の
修飾子
2.3.0 New場合によっては、プロップに対して「双方向バインディング」を実行する必要があるかもしれません。残念ながら、真の双方向バインディングでは、親コンポーネントにも子コンポーネントにも明らかな変更源がなくても、子コンポーネントが親コンポーネントを変更できるため、メンテナンスの問題が発生します。 モードを使用してイベントをトリガーすることをお勧めする理由です。たとえば、
titlev-bind
v-model これにより、doc オブジェクトの各属性 (タイトルなど) が独立した prop として渡され、更新用の v-on リスナーが追加されます。 リテラル オブジェクトで など) のみを指定できます。
オブジェクトを使用して複数のプロパティを同時に設定する場合、この .sync 修飾子を
v-bind
とともに使用することもできます: <text-document v-bind:title.sync="doc.title"></text-document>
v-bind.sync
を使用します。たとえば、v-bind.sync=”{ title: doc.title }”
、このような複雑な式を解析する際には考慮すべきエッジケースが多数あるため、正しく動作しません。