$ (this) wewnątrz sukcesu AJAX nie działa

103

Próbuję zmienić stary kod, który używa onclick, aby użyć $ (this). Problem polega na tym, że $ (this) nie działa, gdy jest wewnątrz sukcesu. Czy mimo to można to zrobić bez ustawiania go jako 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");

            }   
        }
    });

});
John Magnolia
źródło

Odpowiedzi:

231

Problem

Wewnątrz wywołania zwrotnego thisodwołuje się do jqXHRobiektu wywołania Ajax, a nie do elementu, z którym została powiązana procedura obsługi zdarzenia. Dowiedz się więcej o tym, jak thisdziała JavaScript .


Rozwiązania

Jeśli ES2015 + jest dla Ciebie dostępny, użycie funkcji strzałki byłoby prawdopodobnie najprostszą opcją:

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

Możesz ustawić contextopcję :

Ten obiekt stanie się kontekstem wszystkich wywołań zwrotnych związanych z Ajaxem. Domyślnie kontekstem jest obiekt, który reprezentuje ustawienia AJAX używane w wywołaniu ( $.ajaxSettingspołączone z ustawieniami przekazanymi do $.ajax). (...)

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

lub użyj $.proxy:

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

lub zachowaj odniesienie do wartości thispoza callbackiem:

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
    }
});

Związane z

Felix Kling
źródło
1
Ponieważ staję się coraz lepszy z JavaScript i buduję coraz większy, złożony projekt, w końcu trochę to rozgryzłem, ale zobaczenie tej odpowiedzi bardzo pomaga mi wiedzieć, że moje założenia są poprawne, a nie tylko teoria, więc osobiście dziękuję, nawet jeśli sprzeciwia się polityce komentarzy SO! =)
JasonDavis
Zgadzam się (i dziękuję), wszystkie trzy opcje działają. Nie wiedziałem o opcji kontekstu Ajax. Drobną wadą jest to, że moje IDE (Phpstorm) nie rozpoznaje opcji rozwiązuje problem z zakresem, który z łatwością wykrywa w zamknięciach JS, takich jak ten. Dodanie opakowania proxy sprawia, że ​​ostrzeżenie znika, więc kontekst: to musi być nieznana sztuczka na jego prawdopodobnie gigantycznej liście heurystycznej.
scipilot
To samo dotyczy opcji kontekstowej. Działał doskonale.
Anna_MediaGirl,
Doskonały przykład!
Jawwad Rizwan
-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) {
                } 


});
Vishal Sanwar
źródło