v-on:click não funciona no meu componente Vue.js

Estou desenvolvendo uma tela no Vue.js e quando eu clico no botão não mostra nenhum erro no console, mas também não imprime a mensagem que deveria aparecer. 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">
    <teste v-on:click="testeFunction"></teste>
  </div>
</template>

<script>
import Teste from './components/Teste'

export default {
  name: 'app',
  methods: {
    testeFunction: function (event) {
      console.log('clicou')
    }
  },
  components: {
    Teste
  }
}
</script>

Teste.vue

<template>
  <div>
    clique aqui
  </div>
</template>

<script>
export default {
  name: 'teste',
  data () {
    return {
      msg: 'Bem vindo ao seu App Vue.js'
    }
  }
}
</script>

O porquê o v-on:click não funciona no componente Vue.js é que se você quiser ouvir um evento nativo no elemento raiz de um componente, você pode usar o modificador .native para v-on, como a seguir:

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

Existe a opção de usar @click.native:

<template>
  <div id="app">
    <teste @click.native="testeFunction"></teste>
  </div>
</template>

Mas atualmente este jeito de resolver é considerado um antipadrão no Vue. Caso você esteja usando Vue 2, uma solução pode ser usar $emit

Solucionando v-on:click no Vue 2

Teste.vue (componente)

<teste @click="$emit('meu-evento')"></teste>

App.vue

<teste @my-event="testeFunction"></teste>

Então ao invés de usar v-on:click ou o atalho @click, use v-on:my-event ou somente @meu-evento.

Solucionando v-on:click no Vue 3

O Vue 3 nos ajuda a criar um wrapper mais simples com menos configuração, usando apenas v-bind="$attrs" . Ao usar isso em componentes filho, não apenas nosso ouvinte funcionará diretamente do pai, mas também quaisquer outros atributos também funcionarão como fariam com um <div> normal.

Portanto, com relação a essa questão, não precisaremos atualizar nada no Vue 3 e seu código ainda funcionará bem, pois <div> é o elemento raiz aqui e ouvirá automaticamente todos os eventos filhos. Exemplo:

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");
<script src="//unpkg.com/[email protected]"></script>
<div id="myApp">
  <base-input 
    label="Search: "
    placeholder="Search"
    @keyup="search">
  </base-input><br/>
</div>