Подписка на нативные события в компонентах
Иногда нужно подписаться на нативные события браузера на корневом элементе компонента. В таких случаях можно применять модификатор .native
для v-on
:
<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"
. Для таких элементов как <input>
, вы также можете захотеть работоспособности с v-model
, для чего бывает полезно создать новое вычисляемое свойство для слушателей, например inputListeners
указанный ниже:
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>
`
})
Теперь компонент <base-input>
стал полностью прозрачной обёрткой, что означает, что его можно использовать точно также, как и обычный элемент <input>
: все те же атрибуты и слушатели будут работать без указания модификатора .native
.
Last updated
Was this helpful?