关于jquery绑定事件、解绑、事件冒泡的探索

在最近的项目中,我发现了jquery一个神奇的现象,有关于绑定事件以及事件解除绑定,让我对jquery获取指定的DOM元素有了更新的理解,下面我想描述一下这个有趣的经历。
有一个需求是这样的:
页面上有一个投票按钮,点击“给TA投票”按钮会调用ajax给后台传数据,后台处理好数据后,如果成功的话会弹一个投票成功的弹窗,用来提示用户,“给TA投票”按钮会变为“已投票”,同时这个按钮将不能再次被点击。于是这里就有了给DOM元素绑定事件以及事件解除绑定的问题。

关于jquery绑定事件、解绑、事件冒泡的探索

其实解决这个问题很简单:
最简单的办法:使用off()

html:
<div class="voteBtn">给TA投票</div>

js:
$('.voteBtn').on('click',function () {
    var $this = $(this);
    $.ajax({
        url:url,
        data:data,
        type:'POST',
        dataType:'json',
        success:function( data){
            if( data.status == 'success'){
                alert('投票成功');
                $this.off('click').text('今日已投票');
            }else if( data.status == 'error'){
                alert(data.data.msg);
            }
        }
    });
})

BUT 我想能不能不用off()呢?于是我又想了另外一个办法:
如果我再给 voteBtn 一个class————“voteActive”,然后我使用选择器选择voteActive这个DOM元素,给它绑定click事件,在click事件内部再把这个voteActive类删掉,这样,选择器选择不到voteActive这个DOM元素,我给一个选择不到的元素绑定事件不就相当于没绑吗!我自认为很机智,实际上事实并非如此。
以下是我愚蠢的代码:

$('.voteBtn.voteActive').on('click',function () {
    var $this = $(this);
    $.ajax({
        url:url,
        data:data,
        type:'POST',
        dataType:'json',
        success:function( data){
            if( data.status == 'success'){
                alert('投票成功');
                $this.removeClass('voteActive').text('今日已投票');
            }else if( data.status == 'error'){
                alert(data.data.msg);
            }
        }
    });
})

事实上,这么写第二次点击投票按钮还是会执行点击事件,为什么呢?
这是因为:
第二次点击按钮时,虽然$('.voteBtn.voteActive')不能成功获取到投票按钮这个DOM元素了,但是,我把$('.voteBtn.voteActive')在控制器输出了一下,得到了这样的结果:

关于jquery绑定事件、解绑、事件冒泡的探索

虽然length是等于0了,证明没有获取到$('.voteBtn.voteActive')这个元素,但是它的context却是document,这说明我的第二次点击其实是把事件绑定到了document上,所以我再次点击投票按钮时,其实相当于点击的是document。原来事件冒泡到了父级元素上!!!

这时,我想到了用on绑定事件的另一种用法:

$('document').on('click','.voteActive',function () {
    var $this = $(this);
    //其他代码...
    $this.removeClass('voteActive');
    //其他代码...
});

这个用法的意思是:
给document绑定一个click事件,如果冒泡冒到voteActive上时,执行这个事件,否则不执行。这样我的第二个方法就能正常使用了。

这次探索更新了我对事件绑定的一些理解,并不是获取不到指定的元素绑定的事件就一定不奏效,别忘了还有事件冒泡呀!思想不要太简单!
好了,为了验证自己的一个脑洞,进行了这样一次尝试,也算有些收获。希望继续努力吧~

相关推荐