使用$(this)选择器时,不在方法中添加类

时间:2011-07-20 20:24:02

标签: javascript jquery jquery-selectors

有人可以解释为什么这段代码有效:

$('#FonykerUsernameRegister').blur(function(){
            if($(this).val().length > 2) {
                $.ajax({
                    url: '<?php echo $html->url('/fonykers/validate_username',true); ?>' + '/' + $(this).val(),
                    dataType: 'json',
                    type: 'POST',
                    success: function(response) {
                        if(!response.ok) {
                            $('#FonykerUsernameRegister').addClass('error');
                            error.html(response.msg);
                            error.fadeIn();
                        } else {
                            if($('#FonykerUsernameRegister').is('.error')) {
                                $('#FonykerUsernameRegister').removeClass('error');
                            }
                            $('#FonykerUsernameRegister').addClass('ok');
                        }
                    },
                    error:function (xhr, ajaxOptions, thrownError){
                        alert(xhr.statusText);
                        alert(thrownError);
                    } 
                });        
            } else {
               error.html('Username must have at least 3 characters');
               error.fadeIn();
               $('#FonykerUsernameRegister').addClass('error');
            }
        });

与此相反:

$('#FonykerUsernameRegister').blur(function(){
            if($(this).val().length > 2) {
                $.ajax({
                    url: '<?php echo $html->url('/fonykers/validate_username',true); ?>' + '/' + $(this).val(),
                    dataType: 'json',
                    type: 'POST',
                    success: function(response) {
                        if(!response.ok) {
                            $(this).addClass('error');
                            error.html(response.msg);
                            error.fadeIn();
                        } else {
                            if($(this).is('.error')) {
                                $(this).removeClass('error');
                            }
                            $(this).addClass('ok');
                        }
                    },
                    error:function (xhr, ajaxOptions, thrownError){
                        alert(xhr.statusText);
                        alert(thrownError);
                    } 
                });        
            } else {
               error.html('Username must have at least 3 characters');
               error.fadeIn();
               $(this).addClass('error');
            }
        });

我假设第二个更优化,所以如果可能的话我宁愿使用这种方式,但它不是在元素上设置类。

5 个答案:

答案 0 :(得分:2)

因为成功处理程序中的“this”不指向元素(#FonykerUsernameRegister)。

在这种情况下你可以使用闭包。

var $this = $(this); //Set this before you make a ajax call

并在成功处理程序中使用$ this;

success: function(response) {
                        if(!response.ok) {
                            $this.addClass('error');
                            error.html(response.msg);
                            error.fadeIn();
                        } else {
                            if($this.is('.error')) {
                                $this.removeClass('error');
                            }
                            $this.addClass('ok');
                        }
                    }

答案 1 :(得分:2)

第一个代码(工作代码)通过id引用元素:jQuery $函数基本上是document.getElementById的替代。

在第二个代码中,当您尝试使用this引用元素时,范围是this可能会引用请求对象或window。如果要将this对象与所需范围一起使用,解决方案是使用proxy方法绑定处理函数,或者将目标元素作为变量使用以在闭包中使用

在这两种方法中,使用proxy最不可能导致循环引用。你在这里给出的代码是安全的,但如果在某些时候从DOM中删除目标元素,那么当你在闭包中使用元素引用时你真的需要注意自己 - 那么你可能会遇到浏览器的垃圾收集器的情况无法释放与元素相关的资源,因为闭包是持有一个引用指针。

所有proxy都是创建具有指定范围的闭包,请参阅文档here

如需进一步阅读范围,请查看this MDC document和此MDC scope "cheat sheet"

<强>关闭:

$('#FonykerUsernameRegister').blur(function(){
    var target = $(this);
    if($(this).val().length > 2) {
        $.ajax({
            url: '<?php echo $html->url('/fonykers/validate_username',true); ?>' + '/' + $(this).val(),
            dataType: 'json',
            type: 'POST',
            success: function(response) {
                if(!response.ok) {
                    target.addClass('error');
                    error.html(response.msg);
                    error.fadeIn();
                } else {
                    if(target.is('.error')) {
                        target.removeClass('error');
                    }
                    target.addClass('ok');
                }
            },
            error:function (xhr, ajaxOptions, thrownError){
                alert(xhr.statusText);
                alert(thrownError);
                alert(target);
            } 
        });        
    } else {
       error.html('Username must have at least 3 characters');
       error.fadeIn();
       $(this).addClass('error');
    }
});

<强>代理

$('#FonykerUsernameRegister').blur(function(){
    if($(this).val().length > 2) {
        $.ajax({
            url: '<?php echo $html->url('/fonykers/validate_username',true); ?>' + '/' + $(this).val(),
            dataType: 'json',
            type: 'POST',
            success: $.proxy(function(response) {
                if(!response.ok) {
                    $(this).addClass('error');
                    error.html(response.msg);
                    error.fadeIn();
                } else {
                    if($(this).is('.error')) {
                        this.removeClass('error');
                    }
                    $(this).addClass('ok');
                }
            }, this),
            error:$.proxy(function (xhr, ajaxOptions, thrownError){
                alert(xhr.statusText);
                alert(thrownError);
                alert(this);
            }, this) 
        });        
    } else {
       error.html('Username must have at least 3 characters');
       error.fadeIn();
       $(this).addClass('error');
    }
});

答案 2 :(得分:0)

在第二个版本中,成功回调内的this指针不再指向jQuery选择 - 它指向请求对象。尝试这样的事情:

$('#FonykerUsernameRegister').blur(function(){
    var self = this; // preserve the 'this' pointer
    $.ajax({
         // blabla
         success: function(response) {
             // replace all references to 'this' with 'self', eg
             $(self).addClass('error');

         }
    });
});

答案 3 :(得分:0)

您必须隐藏this的值以便在其他(回调)函数中使用。

在模糊处理程序的顶部,添加:

  var register = this, $register = $(register);

(当然,根据您的喜好使用其他名称。)

然后,在ajax处理函数内部,您可以使用“$ register”而不是“$('#FonykerUsernameRegister')”。

答案 4 :(得分:0)

成功回调不会在与.blur回调相同的上下文中调用,因此成功回调中的this很可能是指window或者ajax对象。还有另一种方法可以通过缓存$(this)来实现这一点,$('#FonykerUsernameRegister').blur(function(){ var $this = $(this); //Cache our reference to #FonykerUsernameRegister if($this.val().length > 2) { $.ajax({ url: '<?php echo $html->url('/fonykers/validate_username',true); ?>' + '/' + $this.val(), dataType: 'json', type: 'POST', success: function(response) { if(!response.ok) { $this.addClass('error'); error.html(response.msg); error.fadeIn(); } else { if($this.is('.error')) { $this.removeClass('error'); } $this.addClass('ok'); } }, error:function (xhr, ajaxOptions, thrownError){ alert(xhr.statusText); alert(thrownError); } }); } else { error.html('Username must have at least 3 characters'); error.fadeIn(); $this.addClass('error'); } }); 将通过范围链传递给成功回调。见下文:

{{1}}