Vue v-on: клик не работает на компоненте

Я пытаюсь использовать директиву on click внутри компонента, но он не работает. Когда я нажимаю компонент, ничего не происходит, когда я должен получить "тестовый клик" в консоли. Я не вижу никаких ошибок в консоли, поэтому я не знаю, что я делаю неправильно.

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(компонент)

<template>
  <div>
    click here
  </div>
</template>

<script>
export default {
  name: 'test',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

Ответы

Ответ 1

Если вы хотите прослушать родное событие в корневом элементе компонента, вы должны использовать модификатор . native для v-on, как показано ниже:

<template>
  <div id="app">
    <test v-on:click.native="testFunction"></test>
  </div>
</template>

или в сокращенном виде, как это предлагается в комментарии, вы также можете:

<template>
  <div id="app">
    <test @click.native="testFunction"></test>
  </div>
</template>

Ответ 2

Я думаю, что функция $emit работает лучше, чем я думаю, о чем вы просите. Он сохраняет ваш компонент отдельно от экземпляра Vue, чтобы он многократно использовался во многих контекстах.

<template>
  <div id="app">
    <test @click="$emit('test-click')></test>
  </div>
</template>

Использовать его в HTML

<test @test-click="testFunction">

Ответ 3

Нативные события компонентов не доступны напрямую из родительских элементов. Вместо этого вы должны попробовать v-on:click.native="testFunction", или вы также можете v-on:click.native="testFunction" событие из компонента Test. Как v-on:click="$emit('click')".

Ответ 4

Немного многословно, но вот как я это делаю:

@click="$emit('click', $event)"

Ответ 5

Это ответ @Neps, но с деталями.


Примечание: ответ @Saurabh больше подходит, если вы не хотите изменять свой компонент или не имеете к нему доступа.


Почему @click просто не работает?

Компоненты сложны. Один компонент может представлять собой небольшую необычную оболочку для кнопок, а другой - целую таблицу с кучей логики внутри. Vue не знает, что именно вы ожидаете, когда связываете v-model или используете v-on поэтому все это должно обработать создатель компонента.

Как обрабатывать событие клика

Согласно Vue docs, $emit передает события родителю. Пример из документов:

Основной файл

<blog-post
  @enlarge-text="onEnlargeText"
/>

Составная часть

<button @click="$emit('enlarge-text')">
  Enlarge text
</button>

(@ - это сокращение от v-on)

Компонент обрабатывает собственное событие click и генерирует parent @enlarge-text="..."

enlarge-text можно заменить click чтобы он выглядел так, как будто мы обрабатываем собственное событие щелчка:

<blog-post
  @click="onEnlargeText"
></blog-post>
<button @click="$emit('click')">
  Enlarge text
</button>

Но это еще не все. $emit позволяет передавать определенное значение с событием. В случае встроенного click значением является MouseEvent (событие JS, которое не имеет ничего общего с Vue).

Vue сохраняет это событие в переменной $event. Таким образом, было бы лучше создать $event с событием, чтобы создать впечатление использования нативного события:

<button v-on:click="$emit('click', $event)">
  Enlarge text
</button>