Как упоминалось Крисом Фрицем (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>
Важно: всегда используйте kebab-case в названиях событий. Для получения дополнительной информации и демонстрации этого пункта, пожалуйста, ознакомьтесь с этим ответом: 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>
Но для сложных компонентов с вложенными элементами, где нам нужно применить атрибуты и события к основному <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>
person
palaѕн
schedule
11.05.2020