jQuery를 사용하여 클래스 변경시 이벤트를 발생시키는 방법은 무엇입니까?


90

나는 다음과 같은 것을 갖고 싶다.

$('#myDiv').bind('class "submission ok" added'){
    alert('class "submission ok" has been added');
});

답변:


169

클래스가 변경 될 때 발생하는 이벤트가 없습니다. 대안은 프로그래밍 방식으로 클래스를 변경할 때 수동으로 이벤트를 발생시키는 것입니다.

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

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

최신 정보

이 질문은 일부 방문자를 모으는 것으로 보이므로 new를 사용하여 기존 코드를 수정하지 않고도 사용할 수있는 접근 방식의 업데이트가 있습니다 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특히, 크롬 (26), FF (14), IE 11 새 브라우저에서만 사용할 수 있습니다, 오페라 15, 사파리 6 참조 MDN 자세한 내용은. 레거시 브라우저를 지원해야하는 경우 첫 번째 예제에서 설명한 방법을 사용해야합니다.


이 답변의 완성에서 나는 이것을 발견했습니다 : stackoverflow.com/a/1950052/1579667
Benj

1
@Benj 그것은 사용 trigger()으로 인해 매우 구식이라는 점에 유의하지만 내 원래 답변 (즉 , 사용)과 동일 bind()합니다. 그래도 어떻게 '완성'하는지 모르겠습니다
Rory McCrossan

내 경우에는 내가 DOM 노드가 특정 클래스가있을 때 이벤트를 발생하기 위해 필요한 MutationObserver나를 위해 작품
마리오

이것은 필터가있는이 솔루션의 개선 된 형태입니다. 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 요소를 통한 클래스 속성의 직접 조작) MutationObserver여기에 허용 된 답변에 설명 된대로 s와 같은 것을 사용해야 합니다.

또한 이러한 방법에 대한 몇 가지 개선 사항 :

  • 콜백 함수에 인수로 전달 된 특정 클래스와 함께 추가 ( ) 또는 제거 ( ) 되는 클래스에 대한 이벤트를 트리거하고 특정 클래스가 실제로 추가 (이전에 없음) 또는 제거 (이전에 존재) 된 경우에만 트리거됩니다.classAddedclassRemoved
  • 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


2

다음과 같이 사용할 수 있습니다.

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

$(Selector).trigger('ClassChanged')

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

그러나 그렇지 않으면 클래스가 변경 될 때 이벤트를 발생시키는 미리 정의 된 함수가 없습니다.

여기에서 트리거에 대해 자세히 알아 보세요.


1
이벤트 핸들러는 이벤트를 트리거하는 항목과 동일해야합니다. $ (this) .addClass ( 'someClass'); $ (Selector) .trigger ( 'ClassChanged') // 동일한 Selector 여야합니다. $ (Selector) .bind ( 'ClassChanged', data, function () {// stuff});
Meko Perez Estevez 2013 년

3
당신은 여기에서 복사하면 링크도 제공하는 경우 다음 좋은 예 경우 것 같다 stackoverflow.com/questions/1950038/...
Satinder 싱
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.