我试图在组件内使用on单击指令,但它似乎不起作用。当我点击组件时,什么都没有发生,当我应该得到一个“测试点击”在控制台中。我在控制台没有看到任何错误,所以我不知道我做错了什么。

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>

测试。Vue(组件)

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

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

当前回答

App.vue

<div id="app">
    <test @itemClicked="testFunction($event)"/>
</div>

Test.vue

<div @click="$emit('itemClicked', data)">
     click here
</div>

其他回答

我认为$emit函数更适合你的要求。它将组件与Vue实例分离,以便在许多上下文中可重用。

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

在HTML中使用

// Parent component
<test @test-click="testFunction">

如果你想监听组件根元素上的本机事件,你必须使用.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>

参考阅读有关本机事件的更多信息

组件的本机事件不能直接从父元素访问。相反,你应该尝试v-on:点击。native="testFunction",或者你也可以从Test组件发出一个事件。像v:点击= " $发出(点击)”。

正如Chris Fritz (Vue.js核心团队Emeriti)在VueCONF US 2019中提到的那样

如果我们让Kia输入。native然后基输入的根元素从input变成了label突然这个组件就坏了,这并不明显事实上,你可能不会马上发现它除非你有一个很好的测试。相反,通过避免使用.native修饰符,我目前认为这是一种反模式,并将在Vue 3中删除,您将能够显式地定义父元素可能关心添加到哪个元素监听器…

使用Vue 2

使用美元的听众:

因此,如果您正在使用Vue 2,解决这个问题的更好选择是使用完全透明的包装器逻辑。为此,Vue提供了一个$listeners属性,其中包含组件上使用的侦听器对象。例如:

{
  focus: function (event) { /* ... */ }
  input: function (value) { /* ... */ },
}

然后我们只需要在测试组件中添加v-on="$listeners",如下所示:

测试。Vue(子组件)

<template>
  <div v-on="$listeners">
    click here
  </div>
</template>

现在<test>组件是一个完全透明的包装器,这意味着它可以像正常的<div>元素一样使用:所有的侦听器都可以工作,不需要.native修饰符。

演示:

Vue.component(“测试”,{ 模板: <div class="child" v-on="$listeners"> 点击这里 < / div >” }) 新Vue ({ 埃尔:“# myApp”, 数据:{}, 方法:{ testFunction:函数(事件){ console.log(测试点) } } }) Div.child{边框:5px虚线橙色;填充:20 px;} < script src = " https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js " > < /脚本> < div id =“myApp”> <测试@click = " testFunction " > < /测试> < / div >

使用$emit方法:

我们还可以使用$emit方法来实现这个目的,它可以帮助我们侦听父组件中子组件的事件。为此,我们首先需要从子组件中发出一个自定义事件,例如:

测试。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(“测试”,{ 模板: <div class="child" @click="$emit('my-event')" > 点击这里 < / div >” }) 新Vue ({ 埃尔:“# myApp”, 数据:{}, 方法:{ testFunction:函数(事件){ console.log(测试点) } } }) Div.child{边框:5px虚线橙色;填充:20 px;} < script src = " https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js " > < /脚本> < div id =“myApp”> <测试@my-event = " testFunction " > < /测试> < / div >


使用Vue 3

使用v-bind = " $ attrs”:

Vue 3将在许多方面使我们的生活更容易。例如,它将帮助我们创建一个更简单的透明包装器,配置更少,只需使用v-bind="$attrs"。通过在子组件上使用这个,不仅我们的侦听器可以直接从父组件工作,而且任何其他属性也可以像正常的<div>一样工作。

因此,关于这个问题,我们不需要更新Vue 3中的任何内容,您的代码仍然可以正常工作,因为<div>是这里的根元素,它将自动侦听所有子事件。

示例# 1:

const {createApp} = Vue; const Test = { 模板: < div class = "孩子" > 点击这里 < / div >” }; const App = { 组件:{Test}, 设置(){ const testFunction = event => { console.log(点击“测试”); }; 返回{testFunction}; } }; createApp (App) .mount(“# myApp”); Div.child{边框:5px虚线橙色;填充:20 px;} < script src = " / / unpkg.com/vue@next " > < /脚本> < div id =“myApp”> <测试v:点击= " testFunction " > < /测试> < / 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>

App.vue

<div id="app">
    <test @itemClicked="testFunction($event)"/>
</div>

Test.vue

<div @click="$emit('itemClicked', data)">
     click here
</div>