用jQuery创建简单的滑动导航菜单

不好意思,我才发现我以前的文章都写得太长了,读起来很累,尽管自我感觉写得还不错的说……以后技术类文章我尽量写得简明易懂,免得在阅读上花费太多读者的时间。
鄙人一直想学js,但无从下手,水平不够,看书也静不下心来,毕业事又多,还欠了一屁股债没还。考虑了半天,从网上买了本《锋利的jQuery》,好像不少人也推荐过这本书。我觉得这本书写得还不错,很简单易懂,虽然我没看多少……书中的第一章为了向读者表明一下jQuery的链式操作风格,写出了一段导航代码,效果是单击不同的章节名称链接,显示相应的内容,同时高亮显示当前选择的章节。代码很简单,如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>1-5-1</title>
<style type="text/css">
#menu {
width:300px;
}
.has_children{
background : #555;
color :#fff;
cursor:pointer;
}
.highlight{
color : #fff;
background : green;
}
div{
padding:0;
}
div a{
background : #888;
display : none;
float:left;
width:300px;
}
</style>
<!-- 引入 jQuery -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
//等待dom元素加载完毕.
$(document).ready(function(){
$(".has_children").click(function(){
$(this).addClass("highlight") //为当前元素增加highlight类
.children("a").show().end() //将子节点的a元素显示出来并重新定位到上次操作的元素
.siblings().removeClass("highlight") //获取元素的兄弟元素,并去掉他们的highlight类
.children("a").hide(); //将兄弟元素下的a元素隐藏
});
});
</script>
</head>
<body>
<div id="menu">
<div class="has_children">
<span>第1章-认识jQuery</span>
<a>1.1-JavaScript和JavaScript库</a>
<a>1.2-加入jQuery</a>
<a>1.3-编写简单jQuery代码</a>
<a>1.4-jQuery对象和DOM对象</a>
<a>1.5-解决jQuery和其它库的冲突</a>
<a>1.6-jQuery开发工具和插件</a>
<a>1.7-小结</a>
</div>
<div class="has_children">
<span>第2章-jQuery选择器</span>
<a>2.1-jQuery选择器是什么</a>
<a>2.2-jQuery选择器的优势</a>
<a>2.3-jQuery选择器</a>
<a>2.4-应用jQuery改写示例</a>
<a>2.5-选择器中的一些注意事项</a>
<a>2.6-案例研究——类似淘宝网品牌列表的效果</a>
<a>2.7-还有其它选择器么?</a>
<a>2.8-小结</a>
</div>
<div class="has_children">
<span>第3章-jQuery中的DOM操作</span>
<a>3.1-DOM操作的分类</a>
<a>3.2-jQuery中的DOM操作</a>
<a>3.3-案例研究——某网站超链接和图片提示效果</a>
<a>3.4-小结</a>
</div>
</div>
</body>
</html>
我觉得这和网上常见的滑动效果很相近,只是没有滑动的动态而已,那么我们可不可以改成更加平滑呢?而且在单击每一项的标题时,其他已经展开了子内容的标题都会被关上,能不能让它点一下标题就展开,再点一下就关上,并且各大标题之间相互没有干扰呢?折腾试试看!
在点击了章节名称(span)后,其他的章节里面的子元素都会被隐藏,起作用的代码是
.children("a").hide()
那我们直接把它去掉不就行了?那么就先去掉试试。嗯,去掉之后的确可以做到点击章节标题展开代码的效果,但是还有个问题,展开后的章节标题你再点它没有任何反应,展开的栏目收不回来了,怎么办?那是因为代码里面只用了show()这个函数,当然没法收回啦,把show()函数换成slideToggle()就可以了,动画速度不够快?加上参数就可以,代码是
sildeToggle(“fast”)
到此为止,看上去还比较完美,但你注意到没,点击章节标题下面的小标题链接,它也会把展开的章节收起来!一般人是不会想要这种效果的吧。原因出在什么地方呢?就是这一句
$(".has_children").click(function(){
这一句表明含有 class=”has_children” 的整个元素(代码中是div)都是可点的,你的a元素也是处于这个div里面,它当然也是可点的嘛。怎么解决这个问题呢?一步步来想
1、我们只需要让标题可点,所以应该让jQuery找到的元素是span,而不是整个<div class=”has_children”>
2、需要展开的是div里面包含的a元素,而不是别的元素,所以sildeToggle的对象是a
按这样来改的话,我们就可以使用下面的代码:
//等待DOM元素加载完毕
$(document).ready(function(){
$(".has_children span").click(function(){
//为span增加点击事件
$(this).parent().addClass("highlight")
//为当前span的父元素增加高亮,也就是当前的div.has_children
.children("a").slideToggle("fast").end()
//将子节点的a元素显示或收缩,并重新定位为上次操作的元素,即div.has_children
.siblings().removeClass("highlight");
//将兄弟元素(即其他的div.has_children)的高亮属性去掉
});
});
可是这样改了还存在一个问题,大家发现了没,你只有点击章节标题的文字才能执行展开收缩的效果,也就是说,可点击区域仅限于文字,文字旁边的深色空白就浪费了不说,如果字很小,不好点击,用户体验变差了。这个问题就交给俺们的CSS吧
.has_children span{display:block;width:300px;}
让span标签以block的形式展示,可点击区域就变大了。
可以再按照你的喜好,把字体配色什么的都换掉,我的代码就是换了字体和高亮的颜色,还折腾了一点点CSS3的文字阴影效果。
完整的代码如下
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>1-5-1</title>
<style type="text/css">
body{font-family:"微软雅黑", Arial;}
#menu{width:300px;margin:0 auto;}
.has_children{background:#555;color:#FFF;cursor:pointer;text-shadow:1px 0 1px #000;}
.has_children span{display:block;width:300px;}
.highlight{color:#FFF;background:#555;}
div{padding:0;}
div a{background:#888;display:none;float:left;width:300px;text-shadow:1px 0 1px #333;}
</style>
</head>
<body>
<div id="menu">
<div class="has_children">
<span>第1章 - 认识</span>
<a>1.1 - Javascript和Javascript库</a>
<a>1.2 - 加入jQuery</a>
<a>1.3 - 编写简单jQuery代码</a>
<a>1.4 - jQuery对象和DOM对象</a>
<a>1.5 - 解决jQuery和其他库的冲突</a>
<a>1.6 - jQuery开发工具和插件</a>
<a>1.7 - 小结</a>
</div>
<div class="has_children">
<span>第2章 - jQuery选择器</span>
<a>2.1 - jQuery选择器是什么</a>
<a>2.2 - jQuery选择器的优势</a>
<a>2.3 - jQuery选择器</a>
<a>2.4 - 应用jQuery改写示例</a>
<a>2.5 - 选择器中的一些注意事项</a>
<a>2.6 - 案例研究——类似淘宝网品牌列表的效果</a>
<a>2.7 - 还有其他选择器么?</a>
<a>2.8 - 小结</a>
</div>
<div class="has_children">
<span>第3章 - jQuery中的DOM操作</span>
<a>3.1 - DOM操作的分类</a>
<a>3.2 - jQuery中的DOM操作</a>
<a>3.3 - 案例研究——某网站超链接和图片提示效果</a>
<a>3.4 - 小结</a>
</div>
</div>
</body>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script>
//等待DOM元素加载完毕
$(document).ready(function(){
$(".has_children span").click(function(){
//为span增加点击事件
$(this).parent().addClass("highlight")
//为当前span的父元素增加高亮,也就是当前的div.has_children
.children("a").slideToggle("fast").end()
//将子节点的a元素显示或收缩,并重新定位为上次操作的元素,即div.has_children
.siblings().removeClass("highlight");
//将兄弟元素(即其他的div.has_children)的高亮属性去掉
});
});
</script>
</html>
本文只是我读书的时候发出的一点点思考,然后按自己的想法折腾了一下。有的博客的侧边栏的项目就可以收缩和展开,不妨用这种方法试试?
已知的问题
书中的代码没有问题,在主流浏览器下运行正常,我改后的代码在IE6下就有小bug了,求解。
已经有8次占座了,你也来凑个热闹吧
我也想学,但没时间……
看的晕头转向
似乎这里也成了集体博了!
@会律博客:你看了关于页面就知道了,这个博客还是Linxo.cn的时候,本来就是集体博客,现在变成我一个人的了,但依然有人客串
有点不完美,应该是这句造成的:
.children(“a”).slideToggle(“fast”)
这里对每个a标签作用,使每个a标签的高度都变化了,看起来有点被挤压的感觉~
个人觉得如果把这些a标签包裹起来,再对其使用.slideToggle效果会好很多~
@林木木:嗯,你说得很对,实现起来也不困难,我上面只是把书中的js源码进行了小小的改动,讨论一下思考的过程。
至于IE6下的bug,你知道不?我还是想不明白,囧……
@ZH CEXO:这个我倒不清楚诶~~
ie下有bug 有兼容性问题 那不是不好用 是否最新版本已经解决了呢