ZH CEXO's BLOG

header_bg
发表于 | 8 comments

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

用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>

DEMO 1

我觉得这和网上常见的滑动效果很相近,只是没有滑动的动态而已,那么我们可不可以改成更加平滑呢?而且在单击每一项的标题时,其他已经展开了子内容的标题都会被关上,能不能让它点一下标题就展开,再点一下就关上,并且各大标题之间相互没有干扰呢?折腾试试看!

在点击了章节名称(span)后,其他的章节里面的子元素都会被隐藏,起作用的代码是

.children("a").hide()

那我们直接把它去掉不就行了?那么就先去掉试试。嗯,去掉之后的确可以做到点击章节标题展开代码的效果,但是还有个问题,展开后的章节标题你再点它没有任何反应,展开的栏目收不回来了,怎么办?那是因为代码里面只用了show()这个函数,当然没法收回啦,把show()函数换成slideToggle()就可以了,动画速度不够快?加上参数就可以,代码是

sildeToggle(“fast”)

DEMO 2

到此为止,看上去还比较完美,但你注意到没,点击章节标题下面的小标题链接,它也会把展开的章节收起来!一般人是不会想要这种效果的吧。原因出在什么地方呢?就是这一句

$(".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的形式展示,可点击区域就变大了。

DEMO 3

可以再按照你的喜好,把字体配色什么的都换掉,我的代码就是换了字体和高亮的颜色,还折腾了一点点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了,求解。

分类:JavaScript | 标签: , ,

    已经有8次占座了,你也来凑个热闹吧

  1. Todd2010年03月16日@15:03[回复]

    我也想学,但没时间……

  2. aunsen2010年03月17日@20:18[回复]

    看的晕头转向 :twisted:

  3. 会律博客2010年03月20日@16:20[回复]

    似乎这里也成了集体博了!

  4. ZH CEXO2010年03月20日@16:39[回复]

    @会律博客:你看了关于页面就知道了,这个博客还是Linxo.cn的时候,本来就是集体博客,现在变成我一个人的了,但依然有人客串

  5. 林木木2010年03月21日@14:09[回复]

    有点不完美,应该是这句造成的:
    .children(“a”).slideToggle(“fast”)
    这里对每个a标签作用,使每个a标签的高度都变化了,看起来有点被挤压的感觉~
    个人觉得如果把这些a标签包裹起来,再对其使用.slideToggle效果会好很多~

  6. ZH CEXO2010年03月21日@14:26[回复]

    @林木木:嗯,你说得很对,实现起来也不困难,我上面只是把书中的js源码进行了小小的改动,讨论一下思考的过程。
    至于IE6下的bug,你知道不?我还是想不明白,囧……

  7. 林木木2010年03月21日@14:28[回复]

    @ZH CEXO:这个我倒不清楚诶~~

  8. 13亿宝藏2010年05月24日@15:42[回复]

    ie下有bug 有兼容性问题 那不是不好用 是否最新版本已经解决了呢

发表一下看法,占个座什么的,希望垃圾评论者离开

,欢迎您的再次光临!  [修改资料]

:wink: :-| :-x :twisted: :) 8-O :( :roll: :-P :oops: :-o :mrgreen: :lol: :idea: :-D :evil: :cry: 8) :arrow: :-? :?: :!: