我试图在组件中使用on click指令,但它似乎不起作用。当我点击组件时,当我应该点击一下&t 39;在控制台中。我没有在控制台中看到任何错误,所以我不知道自己做错了什么。
的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>
答案 0 :(得分:203)
如果要在组件的根元素上侦听本机事件,则必须使用v-on
的{{3}}修饰符,如下所示:
<template>
<div id="app">
<test v-on:click.native="testFunction"></test>
</div>
</template>
或者简而言之,正如评论中所建议的,您也可以这样做:
<template>
<div id="app">
<test @click.native="testFunction"></test>
</div>
</template>
答案 1 :(得分:12)
我认为$emit
功能对我认为你要求的效果更好。它使您的组件与Vue实例分离,以便在许多上下文中可以重用。
<template>
<div id="app">
<test @click="$emit('test-click')></test>
</div>
</template>
在HTML中使用
<test @test-click="testFunction">
答案 2 :(得分:11)
如Chris Fritz(Vue.js Core Team Emeriti)在VueCONF US 2019中所述
如果我们让起亚输入
.native
,然后基本输入的根元素突然从输入更改为标签,则此组件损坏,并且不明显,实际上,您甚至可能不会立即捕获它除非您有一个非常好的测试。通过避免使用.native
修饰符(我目前认为它会在Vue 3中删除反图案),您可以显式定义父级可能关心哪个元素侦听器已添加到...
$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>
元素一样完全使用:所有监听器都可以工作,而无需使用{{ 1}}修饰符。
演示:
.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;}
$emit
方法:我们也可以为此使用<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
<test @click="testFunction"></test>
</div>
方法,这有助于我们侦听父组件中的子组件事件。为此,我们首先需要从子组件发出custom event,例如:
Test.vue(子组件)
$emit
重要:事件名称始终使用kebab-case。有关这一点的更多信息和演示,请查看以下答案:VueJS passing computed value from component to parent。
现在,我们只需要在父组件中监听此发出的自定义事件,如:
App.vue
<test @click="$emit('my-event')"></test>
因此,基本上,我们将只使用<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"
来创建配置非常简单的更简单的透明包装器。通过在子组件上使用它,不仅我们的侦听器将直接从父组件工作,而且其他任何属性也将像正常的v-bind="$attrs"
一样工作。
因此,关于这个问题,我们不需要更新Vue 3中的任何内容,并且您的代码仍可以正常工作,因为<div>
是此处的根元素,它将自动侦听所有子事件。 / p>
演示1:
<div>
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 />
演示2:
v-bind="$attrs"
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;}
答案 3 :(得分:5)
有点冗长,但这是我的方法:
@click="$emit('click', $event)"
答案 4 :(得分:4)
组件的本机事件不能直接从父元素访问。相反,您应该尝试v-on:click.native="testFunction"
,或者您也可以从Test
组件发出事件。与v-on:click="$emit('click')"
一样。
答案 5 :(得分:4)
它是@Neps' answer,但有详细信息。
注意:如果您不想修改组件或无法访问组件,@Saurabh's answer更合适。
组件很复杂。一个组件可以是一个小巧的按钮包装器,另一个组件可以是内部包含一堆逻辑的整个表。 Vue不知道绑定v-model
或使用v-on
时的确切期望,因此所有这些都应由组件的创建者处理。
根据Vue docs,$emit
将事件传递给父对象。来自文档的示例:
主文件
<blog-post
@enlarge-text="onEnlargeText"
/>
组件
<button @click="$emit('enlarge-text')">
Enlarge text
</button>
({@
是v-on
shorthand)
组件处理本机click
事件并发出父级的@enlarge-text="..."
enlarge-text
可以替换为click
,以使其看起来像我们正在处理本地点击事件:
<blog-post
@click="onEnlargeText"
></blog-post>
<button @click="$emit('click')">
Enlarge text
</button>
但这还不是全部。 $emit
允许通过事件传递特定值。对于本地click
,该值为MouseEvent(与Vue无关的JS事件)。
Vue将事件存储在$event
变量中。因此,最好向事件发出$event
来产生本机事件用法的印象:
<button v-on:click="$emit('click', $event)">
Enlarge text
</button>
答案 6 :(得分:0)
由于JavaScript的限制,Vue无法检测到对数组的以下更改:
就我而言,从Angular迁移到VUE时,我偶然发现了这个问题。修复非常容易,但是却很难找到:
setValue(index) {
Vue.set(this.arr, index, !this.arr[index]);
this.$forceUpdate(); // Needed to force view rerendering
}