Vue3循环对象数组时,如何为每个组件设置不同点击事件?
解决方案:传递函数作为Props实现不同点击事件
问题原因
你当前在cardPropsArray里把scrollFunction设为字符串(比如"musicScroll()"),但Vue无法直接将字符串解析为组件内的方法,所以触发点击时会抛出类型错误:$props.cardProperties.scrollFunction 不是一个函数。
下面提供几种可行的解决方式:
方法1:直接传递组件方法的引用(简单直接)
把父组件里的滚动方法直接作为引用传入数组,而非字符串形式:
App.vue 修改代码
<script> export default { data() { return { cardPropsArray: [ { id: "music", scrollFunction: this.musicScroll, // 直接传递方法引用 title: "Musik", icon: "fa-solid fa-music", text: "/play" }, { id: "mao", scrollFunction: this.maoScroll, title: "Med Andra Ord", icon: "fa-solid fa-hourglass-end", text: "/MAO" } ] }; }, methods: { musicScroll() { const musicDiv = document.getElementById("music"); if(musicDiv != null){ musicDiv.scrollIntoView({behavior: 'smooth'}); } }, maoScroll() { const maoDiv = document.getElementById("mao"); if(maoDiv != null){ maoDiv.scrollIntoView({behavior: 'smooth'}); } } } }; </script>
子组件(card-container)简化代码
可以删除子组件内的滚动方法和冗余的cardProps数据,直接使用props传入的函数:
<template> <div @click="cardProperties.scrollFunction" :id="cardProperties.id" class="flex text-text-color justify-around text-center bg-container-color h-1/6 w-2/12 rounded-3xl shadow-lg m-4 cursor-pointer ease-in-out duration-500 hover:bg-container-hover-color opacity-95" > <div class="py-6"> <h2>{{cardProperties.title}}</h2> <font-awesome-icon class="h-12 my-4" :icon="cardProperties.icon" /> <p>{{cardProperties.text}}</p> </div> </div> </template> <script> export default { name: 'card-container', props: { cardProperties: { type: Object, required: true } } }; </script>
方法2:通过事件触发(Vue推荐的父子通信方式)
如果不想把方法直接传入子组件,可以让子组件点击时触发事件,父组件根据卡片ID处理滚动逻辑:
子组件修改代码
<template> <div @click="handleCardClick" :id="cardProperties.id" class="flex text-text-color justify-around text-center bg-container-color h-1/6 w-2/12 rounded-3xl shadow-lg m-4 cursor-pointer ease-in-out duration-500 hover:bg-container-hover-color opacity-95" > <div class="py-6"> <h2>{{cardProperties.title}}</h2> <font-awesome-icon class="h-12 my-4" :icon="cardProperties.icon" /> <p>{{cardProperties.text}}</p> </div> </div> </template> <script> export default { name: 'card-container', props: { cardProperties: { type: Object, required: true } }, methods: { handleCardClick() { this.$emit('card-click', this.cardProperties.id); // 触发事件并传递卡片ID } } }; </script>
App.vue 修改代码
<template> <card v-for="cardProperties in cardPropsArray" :key="cardProperties.text" :cardProperties="cardProperties" @card-click="handleScroll" /> </template> <script> export default { data() { return { cardPropsArray: [ { id: "music", title: "Musik", icon: "fa-solid fa-music", text: "/play" }, { id: "mao", title: "Med Andra Ord", icon: "fa-solid fa-hourglass-end", text: "/MAO" } ] }; }, methods: { handleScroll(id) { const targetDiv = document.getElementById(id); if(targetDiv) { targetDiv.scrollIntoView({behavior: 'smooth'}); } } } }; </script>
方法3:统一子组件内的滚动逻辑(精简代码)
两个滚动方法逻辑高度相似,仅目标ID不同,可以直接在子组件内根据卡片ID处理滚动,无需传递函数:
子组件修改代码
<template> <div @click="handleScroll" :id="cardProperties.id" class="flex text-text-color justify-around text-center bg-container-color h-1/6 w-2/12 rounded-3xl shadow-lg m-4 cursor-pointer ease-in-out duration-500 hover:bg-container-hover-color opacity-95" > <div class="py-6"> <h2>{{cardProperties.title}}</h2> <font-awesome-icon class="h-12 my-4" :icon="cardProperties.icon" /> <p>{{cardProperties.text}}</p> </div> </div> </template> <script> export default { name: 'card-container', props: { cardProperties: { type: Object, required: true } }, methods: { handleScroll() { const targetDiv = document.getElementById(this.cardProperties.id); if(targetDiv) { targetDiv.scrollIntoView({behavior: 'smooth'}); } } } }; </script>
App.vue 简化数组
删除cardPropsArray里的scrollFunction字段即可:
cardPropsArray:[ { id: "music", title: "Musik", icon: "fa-solid fa-music", text: "/play" }, { id: "mao", title: "Med Andra Ord", icon: "fa-solid fa-hourglass-end", text: "/MAO" } ]
内容的提问来源于stack exchange,提问作者Kron
相关产品推荐
相关产品推荐

