Як згадував Кріс Фріц (Vue.js Core Team Emeriti ) у VueCONF US 2019
якби ми ввели Kia .native
і тоді кореневий елемент базового вводу змінився з вхідного на мітку, раптом цей компонент зламаний, і це не очевидно, і насправді ви можете навіть не зловити його відразу, якщо у вас справді хороший тест. Натомість, уникаючи використання .native
модифікатора, який я зараз вважаю анти-шаблоном, буде видалено у Vue 3, ви зможете чітко визначити, що батьків може хвилюватись, до яких слухачів елементів додано ...
З Vue 2
Використання $listeners
:
Отже, якщо ви використовуєте Vue 2, кращим варіантом вирішення цієї проблеми буде використання повністю прозорої логіки обгортки . Для цього Vue надає $listeners
властивість, що містить об’єкт слухачів, що використовується на компоненті. Наприклад:
{
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}
і тоді нам просто потрібно додати v-on="$listeners"
до такого test
компонента, як:
Test.vue (дочірній компонент)
<template>
<div v-on="$listeners">
click here
</div>
</template>
Тепер <test>
компонент є повністю прозорою обгорткою , тобто він може використовуватися точно як звичайний <div>
елемент: всі слухачі працюватимуть без .native
модифікатора.
Демонстрація:
Vue.component('test', {
template: `
<div class="child" v-on="$listeners">
Click here
</div>`
})
new Vue({
el: "#myApp",
data: {},
methods: {
testFunction: function(event) {
console.log('test clicked')
}
}
})
div.child{border:5px dotted orange; padding:20px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
<test @click="testFunction"></test>
</div>
Використовуючи $emit
метод:
Ми також можемо використовувати $emit
метод для цієї мети, який допомагає нам слухати події дочірніх компонентів у батьківському компоненті. Для цього нам спочатку потрібно випустити спеціальну подію з дочірнього компонента, наприклад:
Test.vue (дочірній компонент)
<test @click="$emit('my-event')"></test>
Важливо: Для імен подій завжди використовуйте кебаб-регістр. Для отримання додаткової інформації та демонстрації демонстрації цього пункту, будь ласка, ознайомтеся з цією відповіддю: VueJS передає обчислене значення від компонента до батьківського .
Тепер нам просто потрібно прослухати цю емітовану користувацьку подію у батьківському компоненті, наприклад:
App.vue
<test @my-event="testFunction"></test>
Отже, в основному замість v-on:click
або скорочення @click
ми будемо просто використовувати v-on:my-event
або просто @my-event
.
Демонстрація:
Vue.component('test', {
template: `
<div class="child" @click="$emit('my-event')">
Click here
</div>`
})
new Vue({
el: "#myApp",
data: {},
methods: {
testFunction: function(event) {
console.log('test clicked')
}
}
})
div.child{border:5px dotted orange; padding:20px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
<test @my-event="testFunction"></test>
</div>
З Vue 3
Використання v-bind="$attrs"
:
Vue 3 багато в чому полегшить наше життя. Одним із прикладів цього є те, що він допоможе нам створити простішу прозору обгортку з дуже меншим конфігурацією, просто використовуючи v-bind="$attrs"
. Використовуючи це на дочірніх компонентах, не тільки наш слухач буде працювати безпосередньо від батьківського, але й будь-який інший атрибут також працюватиме так само, як і звичайний <div>
.
Отже, стосовно цього питання нам не потрібно буде нічого оновлювати у Vue 3, і ваш код все одно буде нормально працювати, як <div>
це кореневий елемент, і він автоматично прослуховуватиме всі події дитини.
Демонстрація №1:
const { createApp } = Vue;
const Test = {
template: `
<div class="child">
Click here
</div>`
};
const App = {
components: { Test },
setup() {
const testFunction = event => {
console.log("test clicked");
};
return { testFunction };
}
};
createApp(App).mount("#myApp");
div.child{border:5px dotted orange; padding:20px;}
<script src="//unpkg.com/vue@next"></script>
<div id="myApp">
<test v-on:click="testFunction"></test>
</div>
Але для складних компонентів з вкладеними елементами, де нам потрібно застосувати атрибути та події до main <input />
замість батьківської мітки, яку ми можемо просто використовуватиv-bind="$attrs"
Демонстрація №2:
const { createApp } = Vue;
const BaseInput = {
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input v-bind="$attrs">
</label>`
};
const App = {
components: { BaseInput },
setup() {
const search = event => {
console.clear();
console.log("Searching...", event.target.value);
};
return { search };
}
};
createApp(App).mount("#myApp");
input{padding:8px;}
<script src="//unpkg.com/vue@next"></script>
<div id="myApp">
<base-input
label="Search: "
placeholder="Search"
@keyup="search">
</base-input><br/>
</div>
@click.native="testFunction"