$ (this) внутри успеха AJAX не работает

103

Я пытаюсь изменить старый код, который использует onclick, чтобы использовать $ (this). Проблема в том, что $ (this) не работает внутри успеха. Есть ли способ сделать это, не устанавливая его как var.

$('.addToCart').click(function() {

    $.ajax({
        url: 'cart/update',
        type: 'post',
        data: 'product_id=' + $(this).attr("data-id"),
        dataType: 'json',
        success: function(json) {

            if (json['success']) {

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

            }   
        }
    });

});
Джон Магнолия
источник

Ответы:

232

Проблема

Внутри обратного вызова thisотносится к jqXHRобъекту вызова Ajax, а не к элементу, к которому был привязан обработчик событий. Узнайте больше о том, как thisработает в JavaScript .


Решения

Если вам доступен ES2015 +, то , вероятно, самым простым вариантом будет использование стрелочной функции :

$.ajax({
    //...
    success: (json) => {
         // `this` refers to whatever `this` refers to outside the function
    }
});

Вы можете установить contextопцию :

Этот объект станет контекстом всех обратных вызовов, связанных с Ajax. По умолчанию контекст - это объект, который представляет параметры ajax, используемые в вызове ( $.ajaxSettingsобъединенные с параметрами, переданными в $.ajax). (...)

$.ajax({
    //...
    context: this,
    success: function(json) {
         // `this` refers to the value of `context`
    }
});

или используйте $.proxy:

$.ajax({
    //...
    success: $.proxy(function(json) {
         // `this` refers to the second argument of `$.proxy`
    }, this)
});

или сохраните ссылку на значение thisвне обратного вызова:

var element = this;

$.ajax({
    //...
    success: function(json) {
         // `this` refers to the jQXHR object
         // use `element` to refer to the DOM element
         // or `$(element)` to refer to the jQuery object
    }
});

Связанный

Феликс Клинг
источник
1
По мере того, как я становлюсь лучше с JavaScript и строю все более и более сложный проект, я, наконец, несколько понял это, но этот ответ очень помогает мне знать, что мои предположения верны, а не только теория, поэтому я лично благодарю вас, даже если против политики комментариев SO! =)
JasonDavis
Я согласен (и благодарен), все три варианта работают. Я не знал о параметре контекста ajax. Незначительным недостатком является то, что моя IDE (Phpstorm) не распознает этот параметр, решает проблему с областью видимости, которую он помогает обнаруживать при закрытии JS, таких как это. Добавление прокси-оболочки устраняет предупреждение, поэтому контекст: это, должно быть, неизвестный трюк в его предположительно гигантском эвристическом списке.
scipilot
То же самое и с опцией контекста. Работает отлично.
Anna_MediaGirl
Отличный пример!
Jawwad Rizwan 07
-2
jQuery(".custom-filter-options .sbHolder ul li a").each(function () {
    var myStr = jQuery(this).text();
    var myArr = myStr.split(" (");
     url = 'your url'; // New Code
            data = myArr[0];
                try {
                    jQuery.ajax({
                        url : url,
                        context: this,
                        type : 'post',
                        data : data,
                        success : function(data) {
            if(data){
                  jQuery(this).html(data);
            }else{
                  jQuery(this).html(myArr[0]);
            }
                        }
                    });
                } catch (e) {
                } 


});
Вишал Санвар
источник