Слушайте пользовательское событие в Vue.js
Vue.js прекрасно работает с событиями браузера, такими как click
или же mousedown
, Но не работать вообще с пользовательскими событиями. Вот код:
HTML:
<div id="app" style="display: none" v-show="true">
<div v-el:ping v-on:ping="ping">
<div>
<button v-on:click="click">Click</button>
</div>
</div>
</div>
JavaScript:
new Vue({
el: '#app',
data: {
},
methods: {
ping: function (event) {
console.log('Vue ping', event);
alert('Vue ping');
},
click: function (event) {
jQuery(event.target).trigger('ping');
}
},
ready: function () {
console.log(this.$els);
jQuery(this.$els.ping).on('ping', function (event) {
console.log('jQuery ping', event);
alert('jQuery ping');
});
}
});
Я ожидаю тревоги с Vue ping
а также jQuery ping
, Но только позже всплывает.
4 ответа
Vue имеет собственную внутреннюю систему для пользовательских событий, которую вы должны использовать вместо событий JQuery / native DOM:
click: function (event) {
// jQuery(event.target).trigger('ping');
this.$dispatch('ping', event.target) // send event up the parent chain, optionally send along a reference to the element.
// or:
this.$emit('ping') // trigger event on the current instance
}
Редактировать: $dispatch для связи родитель-потомок. Вы, кажется, хотите инициировать пользовательское событие из того же компонента. В этом случае вы могли бы просто вызвать метод.
Если вы все еще хотите прослушать пользовательское событие внутри того же компонента, вы:
- хочу использовать $emit
не может использовать
v-on:custom-event-name
в шаблоне (это только для компонентов). Скорее, добавьте метод события кevents:
:события: { ping: function() {....} }
Вы должны избегать смешивания dom-событий и vue-компонентов, связанных, потому что это разные уровни абстракции.
В любом случае, если вы все еще хотите это сделать, я думаю, вам нужно кэшировать this.el внутри экземпляра vue-component или взять его через свойство computed-property, например
{
computed : {
jqueryEl(){ return $(this.el) }
}
}
И затем вызвать пользовательские события JQuery по this.jqueryEl.trigger('ping')
,
Обязательно позаботьтесь о своевременном обновлении привязок элемента! Например, вы можете динамически связывать события jQuery (а также отменять привязку при уничтожении компонента!) Следующим образом:
ready : function(){
jQuery('body').on('ping.namespace', '[data-jquery="ping"]', function(){ ... })
},
destroy : function(){
jQuery('body').off('ping.namespace')
}
И не забудьте добавить атрибут [data-jquery="ping"]
к элементу, который вы хотели бы ответить на событие ping.
Надеюсь, что эта информация поможет вам достичь ожидаемого результата.
Вот это в ванильном JS:
HTML:
<div id="app">
<div v-el:ping>
<div>
<button v-on:click="click">Click</button>
</div>
</div>
</div>
JS:
(function() {
new Vue({
el: '#app',
data: {
event: null
},
methods: {
ping: function(event) {
alert('Vue ping');
},
click: function(event) {
this.$els.ping.dispatchEvent(this.event);
}
},
ready: function() {
this.event = document.createEvent("HTMLEvents");
this.event.initEvent("ping", true, true);
this.$els.ping.addEventListener('ping', this.ping);
}
});
})();
Я столкнулся с той же проблемой, и решение довольно простое, если вы используете v-autocomplete из Vuetify.
Что я сделал
- Добавьте ключ в данные, я называю это
searchText
- Свяжите это свойство с
v-model:search
- Добавьте обработчик событий под названием
@update:modelValue
- Объявите метод и добавьте этот метод в
@update:modelValue="emptySearchText"
Вот пример.
<v-autocomplete
label="Your Label"
:items="items"
v-model="selected"
v-model:search="searchText"
@update:modelValue="emptySearchText"
multiple>
</v-autocomplete>
data: () => ({
searchText: null
})
methods: {
emptySearchText () {
this.searchText = '';
}
}
Проверьте это для получения дополнительной информации.https://vuetifyjs.com/en/api/v-autocomplete/#events-update:modelValue