Vue.js绑定自定义事件加括号调用方法报错原因
Vue自定义事件绑定加括号报错的原因
两种事件绑定写法的运行逻辑有本质区别,和是不是原生DOM事件没有关系:
- 写
@toggle-favorite="toggleFavorite"时,Vue会直接把toggleFavorite函数本身注册为事件回调。子组件触发事件时,Vue会自动把$emit携带的所有参数按顺序传入这个回调。你在子组件里写了this.$emit("toggle-favorite", this.id),id会被自动传给父组件的方法,逻辑可以正常执行。
对应的子组件触发事件代码:
父组件对应接收参数的方法:toggleFavorite: function () { this.$emit("toggle-favorite", this.id); }toggleFavorite: function (id) { let friendToUpdate = this.friends.find((el) => el.id === id); friendToUpdate.favorite = !friendToUpdate.favorite; } - 写
@toggle-favorite="toggleFavorite()"时,Vue不会把函数本身注册为回调,而是把括号包裹的整段函数调用语句作为内联脚本,事件触发时直接执行这段脚本。你括号里没有传任何参数,相当于执行了无参的toggleFavorite(),方法里接收到的id是undefined,后续执行find查找时拿undefined和好友id做匹配,根本找不到对应元素,返回的friendToUpdate值为undefined,再访问friendToUpdate.favorite自然就会抛出类型错误。
你之前觉得原生@click事件两种写法都能跑,本质是之前写点击事件时要么没用到事件参数,要么手动传了需要的参数——如果写@click="handleClick()"又没手动传$event占位符,方法里同样拿不到原生事件对象,只是之前没用到这个对象所以没触发报错而已。
带括号的正确写法
如果习惯写带括号的调用形式,需要手动用Vue内置的$event占位符接住子组件抛出的参数,再传入方法:
<friend-contact v-for="friend in friends" :data="friend" :key="friend.id" @toggle-favorite="toggleFavorite($event)" > </friend-contact>
这里的$event就对应子组件$emit时传入的第一个参数(也就是你传的id),手动传入后方法就能正常拿到值运行。如果子组件$emit携带了多个参数,后续参数可以通过arguments[1]、arguments[2]的形式依次获取,日常开发只需要接收单个参数时,直接写方法名不加括号是最简便的写法。
内容的提问来源于stack exchange,提问作者shoko-moko
相关产品推荐
相关产品推荐

