需求:鼠标悬停在商品分类上时右侧会出现具体产品分类的浮窗(如下图)。
总体思路是:
- 利用data(){}存储响应式状态,并使用v-if控制浮窗组件是否显示
- 使用@mouseenter和@mouseleave来检测鼠标,当鼠标移动到对应组件时,激活函数调整是否显示的状态为true,浮窗组件就会显示。当鼠标离开,激发函数将状态改为false,浮窗不显示。
- 浮窗组件同样要添加@mouseenter和@mouseleave,确保用户将鼠标从左侧组件移开,浮窗不会消失,以及用户从浮窗移开鼠标,浮窗会消失。
- 使用定时器确保鼠标离开左侧组件时,浮窗不会立刻消失,确保不会抖动频闪,以及用户无法将鼠标移动到浮窗组件中。
<template>
<div class="product-categories">
<div class="category-item"
>
<span class="category-icon"
><img class="icon" src="..\assets\goods.svg"
/></span>
<span class="category-text">采购优选</span>
<span class="category-icon">/</span>
<span class="category-text">抢省钱补贴</span>
</div>
<!-- <youxuan
v-if="ifShow"
class="popup-tooltip"
@mouseenter="cancelHideTooltip"
@mouseleave="hideTooltip"
/> -->
<div
class="category-item"
@mouseenter="showTooltip"
@mouseleave="scheduleHideTooltip"
>
<span class="category-icon">
<img class="icon" src="..\assets\goods.svg" />
</span>
<span class="category-text">电脑</span>
<span class="category-icon">/</span>
<span class="category-text">配件</span>
<span class="category-icon">/</span>
<span class="category-text">办公</span>
<span class="category-icon">/</span>
<span class="category-text">文具</span>
</div>
<div
v-if="ifShow"
class="popup-tooltip"
@mouseenter="showTooltip"
@mouseleave="hideTooltip"
>
<diannao />
</div>
<div class="category-item">
<span class="category-icon"
><img class="icon" src="..\assets\goods.svg"
/></span>
<span class="category-text">家电</span>
<span class="category-icon">/</span>
<span class="category-text">手机</span>
<span class="category-icon">/</span>
<span class="category-text">通信</span>
<span class="category-icon">/</span>
<span class="category-text">数码</span>
</div>
<div class="category-item">
<span class="category-icon"
><img class="icon" src="..\assets\goods.svg"
/></span>
<span class="category-text">工业品</span>
<span class="category-icon">/</span>
<span class="category-text">商业</span>
<span class="category-icon">/</span>
<span class="category-text">农业</span>
<span class="category-icon">/</span>
<span class="category-text">定制</span>
</div>
<div class="category-item">
<span class="category-icon"
><img class="icon" src="..\assets\goods.svg"
/></span>
<span class="category-text">家具</span>
<span class="category-icon">/</span>
<span class="category-text">家装</span>
<span class="category-icon">/</span>
<span class="category-text">家居</span>
<span class="category-icon">/</span>
<span class="category-text">厨具</span>
</div>
<div class="category-item">
<span class="category-icon"
><img class="icon" src="..\assets\goods.svg"
/></span>
<span class="category-text">女装</span>
<span class="category-icon">/</span>
<span class="category-text">男装</span>
<span class="category-icon">/</span>
<span class="category-text">内衣</span>
<span class="category-icon">/</span>
<span class="category-text">配饰</span>
</div>
<div class="category-item">
<span class="category-icon"
><img class="icon" src="..\assets\goods.svg"
/></span>
<span class="category-text">女鞋</span>
<span class="category-icon">/</span>
<span class="category-text">男鞋</span>
<span class="category-icon">/</span>
<span class="category-text">运动</span>
<span class="category-icon">/</span>
<span class="category-text">户外</span>
</div>
<div class="category-item">
<span class="category-icon"
><img class="icon" src="..\assets\goods.svg"
/></span>
<span class="category-text">汽车</span>
<span class="category-icon">/</span>
<span class="category-text">珠宝</span>
<span class="category-icon">/</span>
<span class="category-text">文玩</span>
<span class="category-icon">/</span>
<span class="category-text">箱包</span>
</div>
<div class="category-item">
<span class="category-icon"
><img class="icon" src="..\assets\goods.svg"
/></span>
<span class="category-text">食品</span>
<span class="category-icon">/</span>
<span class="category-text">生鲜</span>
<span class="category-text">健康</span>
<span class="category-icon">/</span>
<span class="category-text">酒类</span>
<span class="category-icon">/</span>
</div>
<div class="category-item">
<span class="category-icon"
><img class="icon" src="..\assets\goods.svg"
/></span>
<span class="category-text">母婴</span>
<span class="category-icon">/</span>
<span class="category-text">童装</span>
<span class="category-icon">/</span>
<span class="category-text">玩具</span>
<span class="category-icon">/</span>
<span class="category-text">宠物</span>
</div>
</div>
</template>
```<script>
import diannao from "./menu_tooltip/2diannao.vue";
import youxuan from "./menu_tooltip/1youxuan.vue";
import jiadian from "./menu_tooltip/3jiadian.vue";
import gongyepin from "./menu_tooltip/4gongyepin.vue";
import jiaju from "./menu_tooltip/5jiaju.vue";
export default {
name: "GoodsMenu",
components: {
youxuan,
diannao,
jiadian,
gongyepin,
jiaju,
},
data() {
return {
ifShow: false,
hideTimer: null,
};
},
methods: {
showTooltip() {
// 如果有隐藏定时器,先清除它
if (this.hideTimer) {
clearTimeout(this.hideTimer);
this.hideTimer = null;
}
this.ifShow = true;
},
scheduleHideTooltip() {
// 设置延迟隐藏,给用户时间将鼠标移到浮窗上
this.hideTimer = setTimeout(() => {
this.ifShow = false;
this.hideTimer = null;
}, 300); // 300ms 延迟
},
hideTooltip() {
// 直接隐藏浮窗(当鼠标从浮窗移出时)
this.ifShow = false;
if (this.hideTimer) {
clearTimeout(this.hideTimer);
this.hideTimer = null;
}
},
},
beforeUnmount() {
// 组件销毁前清除定时器
if (this.hideTimer) {
clearTimeout(this.hideTimer);
}
},
};
</script>
```<style scoped>
.icon {
width: 15px;
}
.product-categories {
margin: 20px auto;
background-color: #fff;
border: 1px solid #eee;
border-radius: 4px;
padding: 15px;
box-sizing: border-box;
}
.category-item {
display: flex;
align-items: center;
padding: 8px 0;
font-size: 14px;
}
.category-item:not(:last-child) {
border-bottom: 1px solid #f5f5f5;
}
.category-icon {
color: #ff5000;
margin: 0 5px;
font-family: "iconfont"; /* 如果使用了图标字体 */
}
.category-text {
color: #333;
margin: 0 5px;
}
.category-text:hover {
color: #ff5000;
cursor: pointer;
}
.popup-tooltip {
position: absolute;
top: 220px;
margin-left: 250px;
width: 800px;
background: #fff;
border: 1px solid #eee;
border-radius: 4px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
z-index: 100;
padding: 20px;
}
</style>
如果直接应用代码,注意子组件需要自己写一下