Vue3中实现鼠标悬浮时单个数组元素的抖动过渡效果
解决Vue3+TypeScript中单个卡片悬浮抖动的问题
你的问题出在使用了全局的shaking变量控制所有卡片的动画状态,所以鼠标悬浮时所有元素都会触发抖动。要实现单个元素抖动,需要跟踪当前悬浮的元素标识,只给对应元素添加动画类。
以下是具体修改方案:
修改步骤
- 替换全局
shaking变量为shakingItemId,用来存储当前需要抖动的元素ID - 调整
hoverShaking方法,接收当前元素的ID作为参数,控制仅该元素触发抖动 - 在模板中,根据当前元素ID是否匹配
shakingItemId来决定是否添加动画类 - 给鼠标事件传递当前元素的ID
修改后的完整代码
Script 部分
<script setup lang="ts"> import Dashboard from '../components/Dashboard.vue' import type { IOption } from '../interfaces/IOption' import { ref } from 'vue' const props = defineProps<{}>() const emits = defineEmits<{}>() const notificaciones = ref(14) const prueba = ref( 'Lorem ipsum dolor sit amet consectetur, adipisicing elit. Corporis numquam, dicta corrupti harum aliquid doloremque dignissimos. Provident ab sed consequatur commodi, aspernatur adipisci dolor veritatis rerum quidem nulla dolore nemo' ) const optionsTest: IOption[] = [ { id: 1, name: 'GitLab', desc: 'Plataforma para control de versiones', url: 'https://gitlab.com/users/sign_in', icono: 'http://localhost:5173/src/assets/gitlab.png', noti: 0 }, { id: 2, name: 'GL', desc: 'Descripcion de la opcion 2', url: '', icono: '', noti: 0 }, { id: 3, name: 'Swagger', desc: `Estructuración de API's`, url: 'https://swagger.io/', icono: 'http://localhost:5173/src/assets/swagger.png', noti: 0 }, { id: 4, name: `Cola de Email's`, desc: 'Emails', url: '', icono: 'http://localhost:5173/src/assets/email.png', noti: 0 }, { id: 5, name: 'Cola de Documentos', desc: 'Documentos', url: '', icono: 'http://localhost:5173/src/assets/documentos2.png', noti: 0 }, { id: 6, name: 'W2P', desc: 'Web to project', url: 'https://call.tpaas.es/?lang=es-ES', icono: '', noti: 0 }, { id: 7, name: 'Reservas', desc: 'Reservas', url: '', icono: '', noti: 0 }, { id: 8, name: 'Servicios BBDD', desc: 'Bases de datos', url: '', icono: 'http://localhost:5173/src/assets/BBDD.png', noti: 0 } ] // 改为跟踪当前需要抖动的元素ID const shakingItemId = ref<number | null>(null) function hoverShaking(itemId: number): void { shakingItemId.value = itemId setTimeout(() => { shakingItemId.value = null }, 750) } </script>
Template 部分
<template> <v-container class="container" :fluid="true"> <v-row no-gutters justify="center"> <!-- 仅当当前元素ID等于shakingItemId时添加动画类 --> <v-col cols="auto" v-for="(item, index) in optionsTest" :class="{ 'apply-shake': shakingItemId === item.id }" :key="item.id"> <Dashboard :item="item" :notificaciones="notificaciones" @mouseover="hoverShaking(item.id)" ></Dashboard> </v-col> </v-row> </v-container> </template>
Style 部分(无需修改)
<style> .cardOption { text-align: center; margin: 5px; margin-left: 35px; margin-top: 5px; margin-bottom: 5px; background-color: #2a5e92; color: white; } .hover-enter-active { transition: all 0.5s ease-in-out; } .prueba { margin: 10px; text-align: center; } @keyframes shake { 10%, 90% { transform: translate3d(-1px, 0, 0); } 20%, 80% { transform: translate3d(2px, 0, 0); } 30%, 50%, 70% { transform: translate3d(-4px, 0, 0); } 40%, 60% { transform: translate3d(4px, 0, 0); } } .apply-shake { animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; transform: translate3d(0, 0, 0); } .bounce:hover { animation-name: bounce; animation-timing-function: ease; } </style>
额外说明
- 把
v-for的key从index改为item.id,符合Vue最佳实践,避免元素复用导致的异常 shakingItemId仅存储当前需要抖动的元素ID,定时器结束后重置为null,确保动画只触发一次
内容的提问来源于stack exchange,提问作者francesco14
相关产品推荐
相关产品推荐

