Estou tentando usar a diretiva on click dentro de um componente, mas ele não parece funcionar. Quando clico no componente, nada acontece quando devo receber um 'teste clicado' no console. Não vejo nenhum erro no console, então não sei o que estou fazendo de errado.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>vuetest</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
App.vue
<template>
<div id="app">
<test v-on:click="testFunction"></test>
</div>
</template>
<script>
import Test from './components/Test'
export default {
name: 'app',
methods: {
testFunction: function (event) {
console.log('test clicked')
}
},
components: {
Test
}
}
</script>
Test.vue (o componente)
<template>
<div>
click here
</div>
</template>
<script>
export default {
name: 'test',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
javascript
vue-component
vuejs2
vue.js
Javier Cárdenas
fonte
fonte
@click.native="testFunction"
Eu acho que a
$emit
função funciona melhor para o que eu acho que você está pedindo. Ele mantém seu componente separado da instância do Vue, para que seja reutilizável em muitos contextos.Use-o em HTML
fonte
@click="$emit('click')"
e de que maneira o componente pai é só usar o regulares@click
@click="$emit('click')"
.É a resposta do @Neps, mas com detalhes.
Nota : A resposta de @ Saurabh é mais adequada se você não quiser modificar seu componente ou não tiver acesso a ele.
Por que o @click não pode funcionar?
Componentes são complicados. Um componente pode ser um pequeno invólucro de botão sofisticado e outro pode ser uma tabela inteira com um monte de lógica dentro. O Vue não sabe exatamente o que você espera quando vincula
v-model
ou usav-on
portanto tudo isso deve ser processado pelo criador do componente.Como lidar com o evento de clique
De acordo com os documentos da Vue ,
$emit
passa eventos para os pais. Exemplo dos documentos:Arquivo principal
Componente
(
@
é av-on
abreviação )O componente lida com
click
eventos nativos e emite os@enlarge-text="..."
enlarge-text
pode ser substituído porclick
para parecer que estamos lidando com um evento de clique nativo:Mas isso não é tudo.
$emit
permite passar um valor específico com um evento. No caso de nativoclick
, o valor é MouseEvent (evento JS que não tem nada a ver com o Vue).O Vue armazena esse evento em uma
$event
variável. Portanto, é melhor emitir$event
um evento para criar a impressão do uso do evento nativo:fonte
Um pouco detalhado, mas é assim que eu faço:
@click="$emit('click', $event)"
fonte
$emit
mas nada está acontecendo. Preciso fazer algo além de$emit
? Postado porEventos nativos de componentes não são acessíveis diretamente a partir de elementos pai. Em vez disso, você deve tentar
v-on:click.native="testFunction"
ou pode emitir um evento doTest
componente também. Likev-on:click="$emit('click')"
.fonte
Conforme mencionado por Chris Fritz (Vue.js Core Team Emeriti ) no VueCONF US 2019
Com o Vue 2
Usando
$listeners
:Portanto, se você estiver usando o Vue 2, uma opção melhor para resolver esse problema seria usar um lógica de invólucro totalmente transparente . Para isso, o Vue fornece uma
$listeners
propriedade que contém um objeto de ouvintes sendo usados no componente. Por exemplo:e só precisamos adicionar
v-on="$listeners"
aotest
componente como:Test.vue (componente filho)
Agora o
<test>
componente é um invólucro totalmente transparente , o que significa que pode ser usado exatamente como um<div>
elemento normal : todos os ouvintes funcionarão sem o.native
modificador.Demo:
Usando
$emit
método:Também podemos usar o
$emit
método para esse fim, o que nos ajuda a ouvir eventos de componentes filho no componente pai. Para isso, primeiro precisamos emitir um evento personalizado do componente filho, como:Test.vue (componente filho)
Importante: Sempre use kebab-case para nomes de eventos. Para obter mais informações e demonstrações sobre esse ponto, consulte esta resposta: VueJS passando o valor calculado do componente para o pai .
Agora, precisamos apenas ouvir esse evento personalizado emitido no componente pai, como:
App.vue
Então, basicamente, em vez de
v-on:click
ou a abreviação@click
, simplesmente usaremosv-on:my-event
ou apenas@my-event
.Demo:
Com o Vue 3
Usando
v-bind="$attrs"
:O Vue 3 tornará nossa vida muito mais fácil de várias maneiras. Um dos exemplos disso é que ele nos ajudará a criar um invólucro transparente mais simples com muito menos configuração usando apenas
v-bind="$attrs"
. Ao usar isso em componentes filhos, não apenas nosso ouvinte funcionará diretamente do pai, mas também qualquer outro atributo também funcionará como normalmente.<div>
.Portanto, com relação a essa pergunta, não precisaremos atualizar nada no Vue 3 e seu código ainda funcionará bem, como
<div>
é o elemento raiz aqui, e ele ouvirá automaticamente todos os eventos filhos.Demo # 1:
Mas para componentes complexos com elementos aninhados nos quais precisamos aplicar atributos e eventos ao main em
<input />
vez do rótulo pai, podemos simplesmente usarv-bind="$attrs"
Demo # 2:
fonte
A partir da documentação :
Devido a limitações no JavaScript, o Vue não pode detectar as seguintes alterações em uma matriz:
No meu caso, me deparei com esse problema ao migrar do Angular para o VUE. A correção foi bastante fácil, mas muito difícil de encontrar:
fonte