# 因使用hover如果频率移入太快,导致元素出现闪动的情况,所以可以通过鼠标移入移出事件来控制,上代码:
1、鼠标移入事件:onmouseover
2、鼠标移出事件:onmouseout
4、鼠标进入事件:onmouseenter
5、鼠标离开事件:onmouseleave
一.、HTML部分:
<div class="menu-list-wrap">
<ul class="menu_list">
<li class="menus_item" v-for="(item, index) in menuDataTest" :key="index"
@mouseover="showSubmenu(item, index)" @mouseout="hideSubmenu(index)">
<div class="menu_item_name">{{ item.name }}</div>
<div class="secondary-menu" v-show="item.columns.length > 0 && showSubMenu && activeSubmenu === index">
<div class="menu-wrap" v-for="(column, columnIndex) in item.columns" :key="columnIndex">
<span>{{ column.name }}</span>
</div>
</div>
</li>
</ul>
</div>
二、 js部分
export default {
data() {
return {
menuDataTest: [
{
name: '导航1',
columns: [
{
name: '导航1二级菜单1111',
},
{
name: '导航1二级菜单222',
},
{
name: '导航1二级菜单1111',
}
],
},
{
name: '导航2',
columns: [
{
name: '导航2二级菜单1111',
},
{
name: '导航2二级菜单222',
},
{
name: '导航2二级菜单1111',
}
],
},
{
name: '导航3',
columns: [
{
name: '导航3二级菜单1111',
},
{
name: '导航3二级菜单222',
},
{
name: '导航3二级菜单1111',
}
],
},
{
name: '导航4',
columns: [
{
name: '导航4二级菜单1111',
},
{
name: '导航4二级菜单222',
},
{
name: '导航4二级菜单1111',
}
],
},
],
menuTimer: null, // 定时器
activeSubmenu: null, // 当前要展示的菜单
showSubMenu: false, // 控制二级菜单显示隐藏值
},
methods: {
// 鼠标移入
showSubmenu(item, index) {
const _this = this;
clearTimeout(_this.menuTimer)
if (item.columns && item.columns.length > 0) {
_debounce(function () {
_this.activeSubmenu = index;
_this.showSubMenu = true
}, 200);
}
},
// 鼠标移出
hideSubmenu(index) {
const _this = this;
if (_this.activeSubmenu === index) {
_this.menuTimer = setTimeout(() => {
_this.activeSubmenu = null;
_this.showSubMenu = false
}, 200)
}
},
}
三.、css部分:
/** 菜单区域 */
.menu-list-wrap {
display: inline-block;
line-height: 80px;
vertical-align: top;
text-align: center;
}
.menu_list {
display: flex;
justify-content: space-between;
.menu_item_name {
font-family: "微软雅黑 Bold", "微软雅黑 Regular", "微软雅黑", sans-serif;
display: inline-block;
color: #333;
font-weight: 400;
font-style: normal;
margin: 0 16px;
cursor: pointer;
height: 80px;
}
}
.menu_item_name:after {
display: block;
content: "";
height: 4px;
width: 64px;
position: absolute;
bottom: 0;
margin: 0 auto;
background: #005CD8;
opacity: 0;
transition: transform 0.2s ease-out, opacity 0.2s ease-out;
transform-origin: 50% 50%;
transform: scale(0.01, 1);
}
.menus_item:hover .menu_item_name:after {
transform: scale(1, 1);
opacity: 1;
}
.menus_item:hover .menu_item_name {
color: #005CD8;
font-weight: 700;
}
.secondary-menu {
display: flex;
flex-direction: row;
justify-content: center;
width: 100vw;
position: fixed;
left: 0px;
z-index: 2;
background: #fff;
box-shadow: 0 4px 10px 0 rgb(0 0 0 / 10%);
animation: secondary-menu-show 0.2s ease-out both;
text-align: left;
padding: 0 100px 0 80px;
}
.menu-wrap {
flex: 1;
margin: 25px;
animation: secondary-menu-show 0.3s ease-out both;
}
四、 优化:这里使用了防抖函数,为了防止频繁操作
/* 防抖函数 */
let timeoutValue = null // 创建一个标记用来存放定时器的返回值
let countValue = 0;
export function _debounce(fn, wait = 1000, immediate = false) {
return function () {
const args = arguments;
if (immediate) {
if (countValue == 0) {
fn.apply(this, arguments)
countValue++;
} else {
if (timeoutValue) {
clearTimeout(timeoutValue) // 每当用户输入的时候把前一个 setTimeout clear 掉
}
timeoutValue = setTimeout(() => {
fn.apply(this, arguments)
}, wait)
}
} else {
if (timeoutValue) {
clearTimeout(timeoutValue) // 每当用户输入的时候把前一个 setTimeout clear 掉
}
timeoutValue = setTimeout(() => {
fn.apply(this, arguments)
}, wait)
}
}()
}