วิธีเริ่มเหตุการณ์ในการเปลี่ยนคลาสโดยใช้ jQuery


คำตอบ:


172

ไม่มีเหตุการณ์ที่เกิดขึ้นเมื่อชั้นเรียนเปลี่ยนไป อีกทางเลือกหนึ่งคือเพิ่มเหตุการณ์ด้วยตนเองเมื่อคุณเปลี่ยนคลาสโดยทางโปรแกรม:

$someElement.on('event', function() {
    $('#myDiv').addClass('submission-ok').trigger('classChange');
});

// in another js file, far, far away
$('#myDiv').on('classChange', function() {
     // do stuff
});

อัปเดต

คำถามนี้ดูเหมือนจะรวบรวมผู้เยี่ยมชมบางส่วนดังนั้นนี่คือการอัปเดตพร้อมแนวทางที่สามารถใช้ได้โดยไม่ต้องแก้ไขโค้ดที่มีอยู่โดยใช้ใหม่MutationObserver:

var $div = $("#foo");
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if (mutation.attributeName === "class") {
      var attributeValue = $(mutation.target).prop(mutation.attributeName);
      console.log("Class attribute changed to:", attributeValue);
    }
  });
});
observer.observe($div[0], {
  attributes: true
});

$div.addClass('red');
.red { color: #C00; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo" class="bar">#foo.bar</div>

โปรดทราบว่าMutationObserverเบราว์เซอร์รุ่นใหม่เท่านั้นโดยเฉพาะ Chrome 26, FF 14, IE 11, Opera 15 และ Safari 6 โปรดดูMDNสำหรับรายละเอียดเพิ่มเติม หากคุณต้องการรองรับเบราว์เซอร์เดิมคุณจะต้องใช้วิธีที่ฉันระบุไว้ในตัวอย่างแรกของฉัน


จากคำตอบนี้ฉันพบสิ่งนี้: stackoverflow.com/a/1950052/1579667
เบญจ

1
@Benj นั่นเหมือนกับคำตอบเดิมของฉัน (เช่นใช้trigger()) แม้ว่าจะทราบว่ามันล้าสมัยมากเนื่องจากการใช้bind()ไฟล์. ฉันไม่แน่ใจว่ามัน 'เสร็จสิ้น' อย่างไร
Rory McCrossan

ในกรณีของฉันฉันจำเป็นต้องเริ่มเหตุการณ์เมื่อโหนดMutationObserver
มาริโอ

1
นี่เป็นรูปแบบที่ปรับปรุงใหม่ของโซลูชันนี้โดยมีตัวกรองstackoverflow.com/a/42121795/12074818
MVDeveloper1

20

คุณสามารถแทนที่ jQuery addClass และฟังก์ชัน removeClass เดิมด้วยฟังก์ชันของคุณเองที่จะเรียกใช้ฟังก์ชันดั้งเดิมจากนั้นจึงทริกเกอร์เหตุการณ์ที่กำหนดเอง (ใช้ฟังก์ชันที่ไม่ระบุตัวตนที่เรียกใช้เองเพื่อให้มีการอ้างอิงฟังก์ชันดั้งเดิม)

(function( func ) {
    $.fn.addClass = function() { // replace the existing function on $.fn
        func.apply( this, arguments ); // invoke the original function
        this.trigger('classChanged'); // trigger the custom event
        return this; // retain jQuery chainability
    }
})($.fn.addClass); // pass the original function as an argument

(function( func ) {
    $.fn.removeClass = function() {
        func.apply( this, arguments );
        this.trigger('classChanged');
        return this;
    }
})($.fn.removeClass);

จากนั้นโค้ดที่เหลือของคุณจะเรียบง่ายอย่างที่คุณคาดหวัง

$(selector).on('classChanged', function(){ /*...*/ });

อัปเดต:

วิธีการนี้ตั้งสมมติฐานว่าคลาสจะถูกเปลี่ยนผ่านเมธอด jQuery addClass และ removeClass เท่านั้น หากคลาสถูกแก้ไขด้วยวิธีอื่น (เช่นการจัดการแอ็ตทริบิวต์คลาสโดยตรงผ่านอิลิเมนต์ DOM) การใช้บางอย่างเช่นMutationObservers ตามที่อธิบายไว้ในคำตอบที่ยอมรับที่นี่ก็จำเป็น

นอกจากนี้ยังมีการปรับปรุงวิธีการเหล่านี้ด้วย:

  • ทริกเกอร์เหตุการณ์สำหรับแต่ละคลาสที่ถูกเพิ่ม ( classAdded) หรือลบ ( classRemoved) โดยคลาสเฉพาะที่ส่งผ่านเป็นอาร์กิวเมนต์ไปยังฟังก์ชันการเรียกกลับและทริกเกอร์ก็ต่อเมื่อมีการเพิ่มคลาสเฉพาะ (ไม่ได้นำเสนอก่อนหน้านี้) หรือลบออก (ก่อนหน้านี้)
  • ทริกเกอร์เฉพาะclassChangedเมื่อมีการเปลี่ยนแปลงชั้นเรียนจริงเท่านั้น

    (function( func ) {
        $.fn.addClass = function(n) { // replace the existing function on $.fn
            this.each(function(i) { // for each element in the collection
                var $this = $(this); // 'this' is DOM element in this context
                var prevClasses = this.getAttribute('class'); // note its original classes
                var classNames = $.isFunction(n) ? n(i, prevClasses) : n.toString(); // retain function-type argument support
                $.each(classNames.split(/\s+/), function(index, className) { // allow for multiple classes being added
                    if( !$this.hasClass(className) ) { // only when the class is not already present
                        func.call( $this, className ); // invoke the original function to add the class
                        $this.trigger('classAdded', className); // trigger a classAdded event
                    }
                });
                prevClasses != this.getAttribute('class') && $this.trigger('classChanged'); // trigger the classChanged event
            });
            return this; // retain jQuery chainability
        }
    })($.fn.addClass); // pass the original function as an argument
    
    (function( func ) {
        $.fn.removeClass = function(n) {
            this.each(function(i) {
                var $this = $(this);
                var prevClasses = this.getAttribute('class');
                var classNames = $.isFunction(n) ? n(i, prevClasses) : n.toString();
                $.each(classNames.split(/\s+/), function(index, className) {
                    if( $this.hasClass(className) ) {
                        func.call( $this, className );
                        $this.trigger('classRemoved', className);
                    }
                });
                prevClasses != this.getAttribute('class') && $this.trigger('classChanged');
            });
            return this;
        }
    })($.fn.removeClass);
    

ด้วยฟังก์ชันการแทนที่เหล่านี้คุณสามารถจัดการคลาสใด ๆ ที่เปลี่ยนแปลงผ่าน classChanged หรือคลาสเฉพาะที่ถูกเพิ่มหรือลบออกโดยตรวจสอบอาร์กิวเมนต์ของฟังก์ชันเรียกกลับ:

$(document).on('classAdded', '#myElement', function(event, className) {
    if(className == "something") { /* do something */ }
});

1
นี้ทำงานได้ดี แต่ใน "ส่วนที่เหลือของรหัส" $(parent_selector).on('classChanged', target_selector, function(){ /*...*/ });จัดการเหตุการณ์ที่ควรจะได้รับการแต่งตั้งให้เลือกเป้าหมายเพื่อให้มีผลผูกพันกับองค์ประกอบใหม่: ใช้เวลาสักพักเพื่อดูว่าเหตุใดองค์ประกอบที่สร้างแบบไดนามิกของฉันจึงไม่ทำให้ตัวจัดการทำงาน ดูlearn.jquery.com/events/event-delegation
Timm

7

ใช้triggerจุดไฟในงานของคุณเอง เมื่อใดก็ตามที่คุณเปลี่ยนคลาสเพิ่มทริกเกอร์ด้วยชื่อ

JS Fiddle DEMO

$("#main").on('click', function () {
    $("#chld").addClass("bgcolorRed").trigger("cssFontSet");
});

$('#chld').on('cssFontSet', function () {

    alert("Red bg set ");
});

เรียนรู้ jQuery: บล็อกบทเรียน jQuery ที่เรียบง่ายและสะดวก


2

คุณสามารถใช้สิ่งนี้:

$(this).addClass('someClass');

$(Selector).trigger('ClassChanged')

$(otherSelector).bind('ClassChanged', data, function(){//stuff });

แต่อย่างอื่นไม่ไม่มีฟังก์ชันที่กำหนดไว้ล่วงหน้าเพื่อเริ่มเหตุการณ์เมื่อคลาสเปลี่ยนไป

อ่านเพิ่มเติมเกี่ยวกับทริกเกอร์ที่นี่


1
ตัวจัดการเหตุการณ์ต้องเป็นรายการเดียวกับที่ทริกเกอร์เหตุการณ์ $ (นี้) .addClass ('someClass'); $ (Selector) .trigger ('ClassChanged') // ต้องเป็น Selector เดียวกัน $ (Selector) .bind ('ClassChanged', data, function () {// stuff});
Meko Perez Estevez

3
ดูเหมือนว่าคุณได้คัดลอกมาจากที่นี่ถ้าใช่ก็ดีถ้าคุณให้ลิงค์ด้วยstackoverflow.com/questions/1950038/…
Satinder singh
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.