Angular中悬停侧边展开div抖动问题求助
侧边展开Div悬停抖动问题修复
问题描述
需要实现侧边展开div的悬停交互:默认状态下div大部分隐藏在屏幕外,仅小部分露出;鼠标悬停露出区域时展开整个div,鼠标移出整个div区域时收起。当前实现存在抖动问题。
当前代码
component.ts
import { Component, Input, OnInit } from '@angular/core'; import { BookingRatingModel } from './booking-rating'; @Component({ selector: 'app-booking-section', templateUrl: './booking-section.component.html', styleUrls: ['./booking-section.component.scss'] }) export class BookingSectionComponent implements OnInit { @Input() bookingRating: BookingRatingModel = new BookingRatingModel(10, 'Nie do opisania'); constructor() { } ngOnInit(): void { } openDetails(){ const rating = document.getElementById('rating'); if(rating) rating.style.right = "28rem" const ratingDetails = document.getElementById('rating-details'); if(ratingDetails) ratingDetails.style.right = "0" } closeDetails(){ const rating = document.getElementById('rating'); if(rating) rating.style.right = "0" const ratingDetails = document.getElementById('rating-details'); if(ratingDetails) ratingDetails.style.right = "-28rem" } }
component.html
<div class="rating" id="rating" (mouseenter)='openDetails()' (mouseleave)='closeDetails()'> <div class="upper"> <div class="title">{{"Sprawdź opinie" | uppercase}}</div> </div> <mat-icon class="icon">star</mat-icon> <div class="number">{{bookingRating.getNumber()}}</div> </div> <div class="rating-details" id="rating-details" (mouseleave)='closeDetails()'> </div>
已尝试的无效方案
- 移除rating元素上的
closeDetails绑定,但div会始终保持展开状态; - 为动画添加0.3秒延迟,但鼠标在延迟期间移出时,div无法正常收起;
- 替换为
mouseover/mouseout事件,问题未解决且事件触发次数增加。
修复方案
抖动核心原因:两个div分别监听事件,展开时元素位置变化导致mouseleave被意外触发,进而反复调用展开/收起逻辑。
解决思路:用父容器包裹两个div,统一监听父容器的悬停事件;通过CSS类控制状态,配合过渡动画实现流畅交互,避免直接操作DOM样式。
修改后代码
component.ts
import { Component, Input, OnInit } from '@angular/core'; import { BookingRatingModel } from './booking-rating'; @Component({ selector: 'app-booking-section', templateUrl: './booking-section.component.html', styleUrls: ['./booking-section.component.scss'] }) export class BookingSectionComponent implements OnInit { @Input() bookingRating: BookingRatingModel = new BookingRatingModel(10, 'Nie do opisania'); isOpen = false; constructor() { } ngOnInit(): void { } toggleDetails(isOpen: boolean) { this.isOpen = isOpen; } }
component.html
<div class="rating-container" (mouseenter)="toggleDetails(true)" (mouseleave)="toggleDetails(false)"> <div class="rating" [class.expanded]="isOpen"> <div class="upper"> <div class="title">{{"Sprawdź opinie" | uppercase}}</div> </div> <mat-icon class="icon">star</mat-icon> <div class="number">{{bookingRating.getNumber()}}</div> </div> <div class="rating-details" [class.expanded]="isOpen"> <!-- 详情内容 --> </div> </div>
component.scss
.rating-container { position: fixed; right: 0; top: 50%; transform: translateY(-50%); display: flex; align-items: center; } .rating { position: relative; right: 0; transition: right 0.3s ease; /* 默认状态下仅小部分露出 */ width: 6rem; padding: 1rem; background: #fff; cursor: pointer; } .rating.expanded { right: 28rem; } .rating-details { position: relative; right: -28rem; transition: right 0.3s ease; width: 28rem; padding: 1rem; background: #f5f5f5; } .rating-details.expanded { right: 0; }
说明
- 父容器
rating-container统一管理悬停状态,避免元素移动导致的事件误触发; - 使用Angular属性绑定
[class.expanded]控制状态,符合组件化开发规范; - CSS过渡动画确保展开/收起过程流畅,彻底消除抖动。
内容的提问来源于stack exchange,提问作者MuzealnaDotacja
相关产品推荐
相关产品推荐

