对JQuery在循环中绑定事件的问题理解

对JQuery在循环中绑定事件的问题理解

在昨天写网页时遇到了一个关于jQuery在循环中绑定事件后部分效果失效的问题,在这里分享一下解决方案

1、先上HTML代码:

在这里需要实现的是鼠标经过li时通过jq animate动画动态增加li元素的高同时使兄弟元素高减少,此外每个li都有指定的img图片,当鼠标经过li时触发mouseover事件使相对的img图片显示同时其他兄弟图片隐藏

            <div class="hoverpart">
                    <img src="images/exhibition1_1.jpg" alt="" class="hoverpart_img1 imgSelected">
                    <img src="images/exhibition1_2.jpg" alt="" class="hoverpart_img2">
                    <img src="images/exhibition1_3.jpg" alt="" class="hoverpart_img3">
                    <img src="images/exhibition1_4.jpg" alt="" class="hoverpart_img4">
                    <img src="images/exhibition1_5.jpg" alt="" class="hoverpart_img5">
                    <ul class="hoverpart_menu">
                        <li class="hoverpart_menu_option">
                            <a href="" title="">
                                <span class="title">1</span>
                                <div class="hoverpart_menu_option_content">我是mouseover事件触发时时显示的内容,平时是隐藏的!(第一条默认显示内容及对应有imgSelected的图片)</div>
                            </a>
                        </li>
                        <li class="hoverpart_menu_option">
                            <a href="" title="">
                                <span class="title">2</span>
                                <div class="hoverpart_menu_option_content">我是mouseover事件触发时时显示的内容,平时是隐藏的!</div>
                            </a>
                        </li>
                        <li class="hoverpart_menu_option">
                            <a href="" title="">
                                <span class="title">3</span>
                                <div class="hoverpart_menu_option_content">我是mouseover事件触发时时显示的内容,平时是隐藏的!</div>
                            </a>
                        </li>
                        <li class="hoverpart_menu_option">
                            <a href="" title="">
                                <span class="title">4</span>
                                <div class="hoverpart_menu_option_content">我是mouseover事件触发时时显示的内容,平时是隐藏的!</div>
                            </a>
                        </li>
                        <li class="hoverpart_menu_option">
                            <a href="" title="">
                                <span class="title">5</span>
                                <div class="hoverpart_menu_option_content">我是mouseover事件触发时时显示的内容,平时是隐藏的!</div>
                            </a>
                        </li>
                    </ul>
                </div>

2、js代码

            for(var i=1;i<=5;i++){
                $(".hoverpart_menu_option").mouseover(function(){
                    $(this).stop().animate({height:"94px"},400).css("background-color","#0055ce")
                    .siblings().stop().animate({height:"37px"},400).css("background-color","#ccc");
                    $(this).addClass("option_selected")
                    .siblings().removeClass("option_selected");
                    //以下失效
                    $("img.hoverpart_img"+i).addClass("imgSelected")
                    .siblings().removeClass("imgSelected");
                    });
               }

在这标注“以下失效”之前的代码都已经成功绑定了每个li,然而此时img并没有随着切换
于是在JS中间添加alert测试i值:

            for(var i=1;i<=5;i++){
                $(".hoverpart_menu_option").mouseover(function(){
                    $(this).stop().animate({height:"94px"},400).css("background-color","#0055ce")
                    .siblings().stop().animate({height:"37px"},400).css("background-color","#ccc");
                    $(this).addClass("option_selected")
                    .siblings().removeClass("option_selected");
                    alert("到这里的i值为:"+i);//插这里
                    //以下失效
                    $("img.hoverpart_img"+i).addClass("imgSelected")
                    .siblings().removeClass("imgSelected");
                    });
               }

结果弹出:
这里写图片描述
而且关键是还弹出5次!!!

。。。。此时我的内心是这样的:
这里写图片描述
于是乎再改alert的位置进行测试:

for(var i=1;i<=5;i++){
                $(".hoverpart_menu_option").mouseover(function(){
                    alert("到这里的i值为:"+i);//插这里
                    $(this).stop().animate({height:"94px"},400).css("background-color","#0055ce")
                    .siblings().stop().animate({height:"37px"},400).css("background-color","#ccc");
                    $(this).addClass("option_selected")
                    .siblings().removeClass("option_selected");
                    //以下失效
                    $("img.hoverpart_img"+i).addClass("imgSelected")
                    .siblings().removeClass("imgSelected");
                    });
               }

这里写图片描述
还是5个6。。。。你怎么不6个6啊!
这里写图片描述
再改!

for(var i=1;i<=5;i++){
                alert("到这里的i值为:"+i);//我再插!
                $(".hoverpart_menu_option").mouseover(function(){
                    $(this).stop().animate({height:"94px"},400).css("background-color","#0055ce")
                    .siblings().stop().animate({height:"37px"},400).css("background-color","#ccc");
                    $(this).addClass("option_selected")
                    .siblings().removeClass("option_selected");
                    //以下失效
                    $("img.hoverpart_img"+i).addClass("imgSelected")
                    .siblings().removeClass("imgSelected");
                    });
               }

这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述
这里写图片描述

果断问百度爸爸
于是乎找到这篇文章:《深入理解JQuery循环绑定事件》

恍然大悟!!!

始终弹出6, 因为function() {} 并没有被立即解析,直到调用的时候才被解析,立即弹出0, 1, 2, 3,4,5是因为使用了function() {}(index)立即被解析,遇到alert,就立即弹出
于是依瓢画葫芦改了一番代码,

3、如下:

            for(var i=1;i<=5;i++){
                    $(".hoverpart_menu_option"+i).bind("mouseover",{index:i},addOne);
                    }
                function addOne(event){
                        var i=event.data.index;
                        $(this).stop().animate({height:"94px"},400).css("background-color","#0055ce")
                        .siblings().stop().animate({height:"37px"},400).css("background-color","#ccc");
                        $(this).addClass("option_selected")
                        .siblings().removeClass("option_selected");
                        $("img.hoverpart_img"+i).addClass("imgSelected")
                        .siblings().removeClass("imgSelected");
                    }

效果终于正确执行,鼠标滑过li对应图片变化正常同时选项高度变化,内容显示。
这里写图片描述

4、原理

按照期望的效果是在for五次循环分别给按钮每个li都绑定mouseover事件,但是五遍循环绑定的是mouseover(i)事件,而不是mouseover(1)、mouseover(2)、mouseover(3)……
与此同时给”img.hoverpart_img”+i中绑定的也是i,而不是1到5,因为在绑定的过程中bind的事件处理函数里的代码并没有运行,因此在触发onmoseover事件之前并不知道i等于几,于是乎就出现了上面的测试中弹出五个6的现象

啊哈哈这难不倒我
这里写图片描述

在这里还有一个javascript的版本,主要是需要闭包解决:
《JavaScript在for循环中绑定事件解决事件参数不同的情况》

5、改装

实际在网页开发过程中代码还可以进一步优化
首先为了方便后台改动,需要微调一下HTML的class:

<!--将img图片class全部统一为hoverpart_img -->
 <img src="images/exhibition1_1.jpg" alt="" class="hoverpart_img imgSelected">
 <img src="images/exhibition1_2.jpg" alt="" class="hoverpart_img">
 <img src="images/exhibition1_3.jpg" alt="" class="hoverpart_img">
 <img src="images/exhibition1_4.jpg" alt="" class="hoverpart_img">
 <img src="images/exhibition1_5.jpg" alt="" class="hoverpart_img">                    

然后再改js:

$(".hoverpart_menu_option").each(function(index, element) {
                $(this).mouseover(function(e) {
                    $(this).stop().animate({height:"94px"},400).css("background-color","#0055ce")
                    .siblings().stop().animate({height:"37px"},400).css("background-color","#ccc");
                    $(this).addClass("option_selected")
                    .siblings().removeClass("option_selected");
                    $("img.hoverpart_img").eq(index).addClass("imgSelected")
                    .siblings("img.hoverpart_img").removeClass("imgSelected");
                });
               })

在这里我们使用了each()方法即jquery的遍历而不是原声的js的for循环遍历,它方便在于each() 方法规定为每个匹配了元素规定运行的函数,同时可以指定index及选择器的位置,将位置指示给eq()方法使用以依次遍历每个img.hoverpart_img,在这里jquery的each方法是通过js里的call方法来实现的,即调用一个对象的一个方法,以另一个对象替换当前对象,通俗来讲就是改变上下文的this指针从而达到改变指向的效果最终实现遍历不同位置。

大功告成,洗洗睡了!
这里写图片描述

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值