Класс не добавляется в метод при использовании селектора $ (this) - PullRequest
0 голосов
/ 21 июля 2011

Может кто-нибудь объяснить, почему этот код работает:

$('#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 ]

2 голосов
/ 21 июля 2011

Первый код (рабочий код) ссылается на элемент по id: функция jQuery $ по сути является заменой document.getElementById.

Во втором коде, когда вы пытаетесь сослаться на элемент, используя this, область действия такова, что this, скорее всего, будет ссылаться на объект запроса или window. Решение, если вы хотите использовать объект this с желаемой областью действия, это использовать метод proxy для привязки функции-обработчика или захватить целевой элемент как переменную для использования в замыкании.

Из двух методов, использование proxy наименее вероятно, приведет к циклической ссылке. Код, который вы здесь привели, безопасен, но вам действительно нужно следить за собой, когда вы используете ссылки на элементы в замыканиях, если целевой элемент будет удален из DOM в какой-то момент - тогда вы потенциально можете столкнуться с ситуацией, когда сборщик мусора в браузере не может освободить ресурсы, связанные с элементом, потому что замыкание удерживает открытым указатель ссылки.

Все, что proxy делает, это создает замыкание с указанной областью, см. Документы здесь .

Для получения дополнительной информации по области, проверьте этот документ MDC и этот "шпаргалку" области охвата MDC

Закрытие:

$('#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');
    }
});

Proxy

$('#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 голосов
/ 21 июля 2011

Потому что «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');
                        }
                    }
0 голосов
/ 21 июля 2011

Обратный вызов успеха не вызывается в том же контексте, что и обратный вызов .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');
        }
    });
0 голосов
/ 21 июля 2011

Вы должны сохранить значение this для использования внутри этих других функций (обратного вызова).

В верхней части обработчика размытия добавьте:

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

(Использоватьконечно, другие имена, как вы предпочитаете.)

Затем внутри функций обработчика ajax вы можете использовать "$ register" вместо "$ ('# FonykerUsernameRegister')".

0 голосов
/ 21 июля 2011

Во второй версии указатель this внутри обратного вызова success больше не указывает на выбор 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');

         }
    });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...