hover之后动画效果
我们可以在需要hover的元素hover之后用::after {content:''; display:block;}添加一个伪div。
ul li a:hover::after{
content: '';
display: block;
position: absolute;
top: 100%;
left: 0;
width: 100%;
height:3px;
background: red;
animation: huadong 0.5s;
}
@keyframes huadong{
0%{
width: 0;
}
100%{
width: 100%;
}
}
下拉列表
- html
<div class="nav">
<ul>
<li><a href="#">导航1</a></li>
<li>
<a class="menuTagger" href="#">导航2</a>
<ul class="menu">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</li>
<li>
<a class="menuTagger" href="#">导航3</a>
<ul class="menu">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</li>
<li><a href="#">导航4</a></li>
<li><a href="#">导航5</a></li>
<li><a href="#">导航6</a></li>
<li><a href="#">导航7</a></li>
</ul>
</div>
- 获取我们需要监听的元素
//通过className获取多个a标签aTags,aTags包装成了一个hash
<script>
let aTags = document.getElementsByClassName('menuTagger')
console.log(aTags)
</script>
- 遍历监听的元素
<script>
let aTags = document.getElementsByClassName('menuTagger')
for(let i=0; i<aTags.length; i++){ //遍历我们监听的元素
aTags[i].onmouseenter = function(x){
console.log(x.currentTarget)//监听的元素
// console.log(x.target) //用户操作的元素
//监听的元素和用户操作的元素可能不是一个元素,如果我们遍历的两个a标签中有个span标签,我们监听的是a标签,很可能用户操作的是span标签。由于onmouseenter比较特殊(onclick可以测试)
//此时我们需要我们监听的元素,所以需要x.currentTarget
}
}
</script>
-
js找弟弟
我们给x.currentTarget这个变量定义个变量名,然后找到我们的下拉菜单,也就是监听元素a标签的弟弟。nextSibling --下一个元素(弟弟元素),因为两个元素之间有空格,用nextSibling很有可能找到的是一个文本,不是我们需要的元素,通过继续nextSibling,终于找到了ul。
找到了一个文本,不是我们需要的
继续找 找到了ul,这才是我们需要的
假如中间有很多空格,我们怎么才能确定我们找到的是文本还是节点呢?我们可以递归用while循环来判断我们找到的是文本还是节点,一直寻找到节点。
弟弟元素的语法和一些值 我们需要记住的是1表示节点,3表示文本
<script>
let aTags = document.getElementsByClassName('menuTagger')
for(let i=0; i<aTags.length; i++){
aTags[i].onmouseenter = function(x){
let a = x.currentTarget
let brother = a.nextSibling //定义当前弟弟元素为a标签的弟弟元素
//如果当前弟弟元素的节点类型是3(文本类型),当前弟弟元素为下一个弟弟的弟弟…不停的找,找到类型不为3为1(节点类型)为止。
while(brother.nodeType === 3){//1是节点类型,3是文本类型
brother = brother.nextSibling
}
console.log(brother)
}
}
</script>
while循环递归寻找节点
如果一个元素后边有很多弟弟元素(节点),怎么确认找到的是我们需要的节点呢,很简单,borther.tag !=='UL'时,一直寻找找到为UL为止。然后给这个弟弟元素添加一个class,达到我们需要的效果。当鼠标移除时,不需要active这个效果,就移除它。
<script>
let aTags = document.getElementsByClassName('menuTagger')
//添加active
for(let i=0; i<aTags.length; i++){
aTags[i].onmouseenter = function(x){
let a = x.currentTarget
let brother = a.nextSibling //定义当前弟弟元素为a标签的弟弟元素
//如果当前弟弟元素的节点类型不是UL,当前弟弟元素为下一个弟弟的弟弟…不停的找,找到为止。
while(brother.tagName !== 'UL'){//如果弟弟元素的tagName不是‘UL’ tagName返回是大写的,ul必须是大写,一定要用小写的:brother.tagName.toLowe !== 'UL' === brother.tagName !== 'UL'
brother = brother.nextSibling
brother.classList.add('active')
}
}
//移除active
for(let i=0; i<aTags.length; i++){
aTags[i].onmouseleave = function(x){
let a = x.currentTarget
let brother = a.nextSibling //定义当前弟弟元素为a标签的弟弟元素
//如果当前弟弟元素的节点类型不是UL,当前弟弟元素为下一个弟弟的弟弟…不停的找,找到为止。
while(brother.tagName !== 'UL'){//如果弟弟元素的tagName不是‘UL’ tagName返回是大写的,ul必须是大写,一定要用小写的:brother.tagName.toLowe !== 'UL' === brother.tagName !== 'UL'
brother = brother.nextSibling
brother.classList.remove('active')
}
}
}
</script>
-
BUG1
鼠标移到监听的a元素上,监听的下拉菜单被触发,这时我们鼠标移动开A标签,查看下拉菜单,发现消失了,因为a和下拉菜单是兄弟关系,是两个元素,应该监听他们的父级元素li标签。
<script>
let liTags = document.getElementsByClassName('menuTagger')
//添加active
for(let i=0; i<liTags.length; i++){
liTags[i].onmouseenter = function(x){
let li = x.currentTarget
let brother = li.getElementsByTagName('ul')[0] //getElements【s】 li下有多个子元素,虽然UL只有一项,也必须加上[0]
brother.classList.add('active')
}
//移除active
liTags[i].onmouseleave = function(x){
let li = x.currentTarget
let brother = li.getElementsByTagName('ul')[0]
brother.classList.remove('active')
}
}
</script>
-
BUG2
a标签hover之后,ul是active状态,当鼠标移动到下拉菜单时,hover效果消失了,ul还是active状态,a和li都是active状态,直接把active加到li上边,此时就不需要找a元素的弟弟ul了,当鼠标移入li,有active状态,鼠标移出,active状态消失。
<script>
let liTags = document.getElementsByClassName('menuTagger')
//添加active
for(let i=0; i<liTags.length; i++){
liTags[i].onmouseenter = function(x){
x.currentTarget.classList.add('active')
}
//移除active
liTags[i].onmouseleave = function(x){
x.currentTarget.classList.remove('active')
}
}
</script>
JS只负责切换状态,至于效果就有css来控制
深度截图_选择区域_20180310154533.png
-
BUG3
由于现在js切换的active状态是监听的那些,所以一些未监听的a元素没有active状态。我们可以给父级元素添加class,监听所有父级元素下有所的ul下的li。
深度截图_选择区域_20180310161349.png
网友评论