在index.html里面引入。
在menu.js脚本里编写代码。
首先写个class关键字定义class类。
constructor定义一个构造构造函数。
参数id对应html里面的样式。
init定义初始方法和调用
在方法里面输出控制台语句,为后面实例的创建作检验。
回到index.html里面new(创建)一个实例对象来使用我们在脚本里面定义的class类。
逻辑对应关系
控制台查看到输出,检验到初始化方法是可用的,证明class类定义的整个流程都能跑通了,能将class引进来且生效了。
下面实现是功能实现
我们想获取盒子(box)下面ul和li标签,和二级菜单下的class样式
回到menu.js脚本,那怎么在class类中获取到DOM?
我们要实现一个类似京东网站的鼠标滑动功能。
可以看到这样一个二级菜单效果,首先有一个延迟效果(计时器的实现),鼠标移入移出事件,鼠标可以斜着锚点,不同于:hover的曲线救国方式。
我们来看下曲线救国方式:css样式中:hover伪类,虽然可以实现,但还是有点不同。鼠标不能斜着移动,会跳到其他二级菜单取,体验并不好。
两种方式对比路径。
我的表达可能不太清晰哈,大家可以去京东网站,手动体验下。
以上就是我们想要实现的一个效果。
我们回到脚本编辑页面。接下来我们在init中设计逻辑功能,所谓的功能都是为了增强用户的交互体验。
给所有li标签绑定一个监听事件
去掉箭头函数的原型是这样的:
语法分析:
HTML DOM addEventListener() 方法,类似遍历的关系
JavaScript forEach() 方法
续上
我们只想要target,我们输出console.log(event),在控制台找到它。
然后打印
看看e.target又是啥。
接下来我们检验鼠标移出移入是否成功
没有问题,已经生效了。
接下来声明一个定时器
延迟200ms后去控制.active
我们来看下效果:
效果:
可以看到每次鼠标移出去,二级菜单都会关闭。鼠标一进来,打开二级菜单。
我们迅速滑动鼠标,这行代码就是只触发鼠标最后一次停留的,中间掠过的不算。(防抖操作)
我们看下原来的效果先。
清除了计时器后(做了防抖操作后的效果)。
只触发鼠标最后一次停留的,中间掠过的不算。
这个代码避免了曲线救国的尴尬(可以斜着拉鼠标到二级菜单,而不是在:hover伪类下走7字的路径)(同样是防抖)
class Menu {
constructor(id) {
this.box = document.querySelector(id)
this.ul = this.box.querySelector('ul')
this.lis = this.box.querySelectorAll('li')
this.subMenuEles = this.box.querySelectorAll('.sub-menu')
this.timer1 = null;
this.timer2 = null;
this.init()
}
init () {
//console.log('menu');
this.lis.forEach(item => {
item.addEventListener("mouseenter", e=> {
let li = e.target
console.log("mouseenter")
if (this.timer1 != null) {
clearTimeout(this.timer1)
}
this.timer1 = setTimeout(() => {
this.subMenuEles.forEach((item) => {
item.classList.remove("active")
})
li.children[1].classList.add("active")
},200)
})
});
this.lis.forEach(item => {
item.addEventListener("mouseleave", e=> {
let li = e.target
console.log("mouseleave")
if (this.timer2 != null) {
clearTimeout(this.timer2)
}
this.timer2 = setTimeout(() => {
this.subMenuEles.forEach((item) => {
li.children[1].classList.remove("active")
})
},200)
})
});
}
}
网友评论