您的位置:首页 > Web前端 > JQuery

我是如何去了解jquery的(五),案例之切换选项卡Tab

2011-11-16 14:38 393 查看

作者:田想兵 博客地址:http://www.cnblogs.com/tianxiangbing

在接下来的章节,我会以案例为主来讲述jquery的一些用法,所以你将看到一个又一个的实例,这些例子的代码量都不会太长,但很有用,前面讲的那么多理论的东西,如果不用在实际过程中,是无法融会贯通的,我尽量的去寻找一些更高效简便的解决方案来解决问题,所以每行代码都很重要。

今天要完成的功能是一般门户网站上常见的tab选项卡切换,我们先来了解为什么要用到选项卡,由于页面屏幕的可见高度限制,一屏往往看到的内容太有限,而又不希望用户用滚动条离开当前视窗,更不希望跳转翻页,这个时候tab就出现了,它的主要作用是缩小内容在页面上所占的空间。最起码你要保证各个选项内容是同级别或同类别的,不能因为要加个功能就东拼西凑,作为一个前端,有时候坚持自己的专业观点很重要,何必为五斗米折腰。

本文案例请点击这里查看

先看下效果图:



这个是从163上抄下来的,去掉了一些样式,我们先来分析下它的dom结构:



很清楚,它的三个标题分别对应了下面的三块内容,然后on这个class就是当前选中的样式。可能很多人拿到这个后,最先想到的是,给三块内容标签加上ID,然后,再点击标题上判断显示哪个ID块。这样做是不错的,但明显的问题是,会影响到这个结构,因为要加属性ID,还有个问题是不能重复使用,并且不方便扩展。然后我们在这个结构上寻找突破口,既然上面的标题和下面的内容都是一致的,那是不是说明它们的索引号(位置)也是一样的呢?明显是,如果不是,你也可以把它轻易的改成是。说到索引号,在jquery有提供一获取索引的方法index(),它的官方解释是:搜索匹配的元素,并返回相应元素的索引值,从0开始计数。

更具体的用户请参照API上的说明,我们这里只需要简单的获取点击标题li在同辈元素中的索引值即可,所以是这样的:

$(function(){

function clickTab(e){

var i=$(this).index();

}

$(".TabList .titleBar li").click(clickTab);

});

然后我们再根据这个索引值来得到下面选项块的内容节点。

$(".tab_content > ul").eq(i)

再我们分别给它们加上选中状态的样式class,加之前移除原先的选中状态,最终的代码应该是这样的:

function clickTab(e){

$(".titleBar li.on").removeClass("on");

$(this).addClass("on");

var i=$(this).index();

$(".tab_content > ul.on").removeClass("on");

$(".tab_content > ul").eq(i).addClass("on");

}

$(".TabList .titleBar li").click(clickTab3);

我靠,是不是有点太简单了,我们试下效果,也确实可行呢?不过短短四行代码就搞定了,这并不是jquery的神奇,这跟用的人有关,可能有些人认为"原生JS"(别人都这么叫)的效率会高很多,jquery只是缩短了代码量,其实不然,我们即使不谈效率问题,这个功能用"原生JS"写也不太可能超过10行,而且你不能把你的使用不当当作jquery的效率低下,就算是有效率影响也不会太大。

是否真的这样就完了呢,这种情况好像只适用于,标题结构和内容结构一致的情况,要是它内容里不是这样很清晰的结果,中间有其他元素的干扰,或者,它的顺序不是按标题的顺序排列的怎么办?正所谓天也有不测之风云,好吧,是不是上面的这种方法就没用了呢,我们还是得回到加ID上去?NO,NO,NO,我们可以继续这样写,如果他的索引是不一致的,我是否可以给他一个一致的索引,这话听起来好像有点矛盾,既然不一致,怎么又能一致呢,除非有第三者插足?恩,我们要做的就是这个第三者,给它加自定义属性,html有这样一个特性,你给节点加所有其他的属性,它都不会报错,如是乎,我就给内容块的每一块都加上一个index属性,对应标题块的顺序。如下图所示



这样,我们根据index属性等于标题上的索引值来获取就行了,如是,我们把刚才的代码改成了这样:

function clickTab2(e){

$(".titleBar li.on").removeClass("on");

$(this).addClass("on");

var i=$(this).index();

$(".tab_content > ul.on").removeClass("on");

$(".tab_content ul").filter("[index='"+i+"']").addClass("on")

}

我们对比下,与刚才的区别是什么,只是在最后一行,第一次的写法是用eq获取到和标题一致的索引内容,而现在,我们用filter筛选出属性index等于标题的索引值的内容项,filter的用法是添加更多的查询条件,你可以直接$(".tab_content ul[index='"+i+"']")这样写,为了更直观,我把它分成了两块查询。不会增加查询成本的哦,亲。

或许到这里,你终于松了一口气,功能完美了。no,no,no,离完美还差得很远,起码现在不是, 为什么呢?你可以试试,在一个页面里添加多个这样的选项卡时,它是否还能正常工作,答案是否定的,你不管点其中任何一个,另一个都会受到影响,这是为什么呢,亲们?这是因为你在改变状态时,查询的范围是针对的整个页面,而不是当前的选项卡class=TabList,那要该怎么做呢?还记得我在《我是如何去了解jquery的(三),事件之点击事件,光棍节特献 》里的全选反选表格操作吗?我有这样一段代码,不知道细心的您有没有发现呢?

$(".list [name='chkAll']").click(function(){

$(this).closest("table").find(":checkbox").not($(this)).attr("checked", $(this).attr("checked"));

});

在这里,我用closest查到它的容器,然后对容器内的节点进行筛选操作,这样就不会引起其他容器的操作了,不信你看我再加一个表格上去,请点击这里查看。那是否我们这里也要用closest然后再find子孙节点呢,这其实不是必须的,在jquery不知道什么版本里,至少在jquery1.4.1里,有了更简洁的一种写法,就是给查询语句第二个参数,这个参数表示,第一个参数的查询条件是针对第二个参数来作范围限定的。所以我们可以改成如此:

function clickTab3(e){

var currentContent=$(this).closest(".TabList");

//$(".titleBar li.on",currentContent).removeClass("on");

currentContent.find(".titleBar li.on").removeClass("on");

$(this).addClass("on");

var i=$(this).index();

$(".tab_content > ul.on",currentContent).removeClass("on");

//currentContent.find(".tab_content > ul.on").removeClass("on");

currentContent.find(".tab_content ul").filter("[index='"+i+"']").addClass("on")

}

看到了没,亲,注释了的才是简洁的写法呢,不要看错了哦,错过了就木有了。到这里功能就算基本上完成了,似乎一个简单的功能,我们却用了三个方法来分析它,有没有变复杂呢?好像还是很简单的嘛,那说明你的智商其实不是你想象的那么低。那我们就继续喽。我们发现需求是在变化的,不变的是结果,现在需求又要变了,我不要点击了才切换,我要鼠标移上去就换,这个是否更简单了呢,我们只需要把clcik换成mouseover即可,好吧,我还要变,我希望这个功能由我来决定是点击还是滑鼠,这个要求真是太过份了,我们无视它,真是太得寸进尺了。不过我们可以做个这样的演示当作练习嘛。代码如下:

html:

<input type="button" value="click" toggleEvent="mouseover" id="btntoggle">

js:
$("#btntoggle").click(function(){
$(".TabList .titleBar li").bind($(this).val(),clickTab3);

$(".TabList .titleBar li").unbind($(this).attr("toggleEvent"));

var temp=$(this).val();//临时变量存储即将要变化的值value;

$(this).val($(this).attr("toggleEvent"));

$(this).attr("toggleEvent",temp);

})

bind是绑定事件,对应的unbind是移除绑定,详情请见API,如果你有任何的疑问都不要问我,请重复再重复阅读本文。或加入我的Q群70210212进行讨论。

本文案例请点击这里查看
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: