jQuery의 맞춤 이벤트?


180

jquery에서 사용자 정의 이벤트 처리를 가장 잘 구현하는 방법에 대한 정보를 찾고 있습니다. 'click'등과 같은 dom 요소에서 이벤트를 연결하는 방법을 알고 있지만 미리보기 기능을 처리하기 위해 작은 자바 스크립트 라이브러리 / 플러그인을 작성하고 있습니다.

내가 가지고있는 규칙 및 데이터 / 사용자 입력 세트에서 dom 요소의 일부 텍스트를 업데이트하는 스크립트가 실행 중이지만이 스크립트가 알 수없는 다른 요소에 표시된 동일한 텍스트가 필요합니다. 내가 필요한 것은 어떻게 든 필요한 스크립트를 생성하는이 스크립트를 관찰하는 좋은 패턴입니다.

어떻게하면 되나요? 사용자 이벤트를 발생시키고 처리하기 위해 jquery의 내장 기능을 간과 했습니까? 아니면 jquery 플러그인이 필요합니까? 이것을 처리하는 가장 좋은 방법 / 플러그인은 무엇이라고 생각하십니까?


3
이 질문을 보는 사람이 필요로하는 경우 내 오래된 문제를 실제로 해결할 수있는 또 다른 프레임 워크 knocknockjs.com 이 있습니다.
Per Hornshøj-Schierbeck가

2
이 질문에서 계속 명성을 얻고있는 사람들은 여전히이 질문을 읽고 있어야합니다. 방금 클라이언트 측 mvc 프레임 워크의 현재 선택을 업데이트하고 싶습니다 : angularjs.org
Per Hornshøj-Schierbeck

그것은 angular v1과 완전히 다르지만 Angular2 ( angular.io )는 많은 약속을 보여 주며 beta / rc에서 나면 첫 번째 선택이 될 것입니다.
Per Hornshøj-Schierbeck

답변:


105

이것 좀 봐 :

( http://web.archive.org/web 의 아카이브 된 버전을 기반으로 만료 된 블로그 페이지 http://jamiethompson.co.uk/web/2008/06/17/publish-subscribe-with-jquery/ 에서 재 인쇄 됨 /20130120010146/http://jamiethompson.co.uk/web/2008/06/17/publish-subscribe-with-jquery/ )


jQuery로 게시 / 구독

2008 년 6 월 17 일

Google Gears의 오프라인 기능과 통합 된 jQuery UI를 작성하기 위해 jQuery를 사용하여 네트워크 연결 상태를 폴링하는 코드를 가지고 놀았습니다.

네트워크 감지 개체

기본 전제는 매우 간단합니다. 정기적으로 URL을 폴링하는 네트워크 감지 개체의 인스턴스를 만듭니다. 이러한 HTTP 요청이 실패하면 네트워크 연결이 끊겼거나 현재 시간에 서버에 연결할 수 없다고 가정 할 수 있습니다.

$.networkDetection = function(url,interval){
    var url = url;
    var interval = interval;
    online = false;
    this.StartPolling = function(){
        this.StopPolling();
        this.timer = setInterval(poll, interval);
    };
    this.StopPolling = function(){
        clearInterval(this.timer);
    };
    this.setPollInterval= function(i) {
        interval = i;
    };
    this.getOnlineStatus = function(){
        return online;
    };
    function poll() {
        $.ajax({
            type: "POST",
            url: url,
            dataType: "text",
            error: function(){
                online = false;
                $(document).trigger('status.networkDetection',[false]);
            },
            success: function(){
                online = true;
                $(document).trigger('status.networkDetection',[true]);
            }
        });
    };
};

여기에서 데모를 볼 수 있습니다. 브라우저가 오프라인에서 작동하도록 설정하고 어떻게되는지 확인하십시오. 아니, 그렇게 흥미 진진하지 않습니다.

트리거 및 바인드

신나는 것은 (또는 적어도 신나는 것은) 응용 프로그램을 통해 상태가 전달되는 방법입니다. jQuery의 트리거 및 바인드 메소드를 사용하여 펍 / 서브 시스템을 구현하는 거의 논의되지 않은 방법을 발견했습니다.

데모 코드는 필요한 것보다 더 모호합니다. 네트워크 감지 개체는 문서에 '상태'이벤트를 게시하여 문서를 적극적으로 수신하고 모든 가입자에게 '알림'이벤트를 게시합니다 (나중에 자세히 설명). 실제 응용 프로그램에는 '알림'이벤트가 언제 어떻게 게시되는지를 제어하는 ​​논리가 더 많을 것입니다.

$(document).bind("status.networkDetection", function(e, status){
    // subscribers can be namespaced with multiple classes
    subscribers = $('.subscriber.networkDetection');
    // publish notify.networkDetection even to subscribers
    subscribers.trigger("notify.networkDetection", [status])
    /*
    other logic based on network connectivity could go here
    use google gears offline storage etc
    maybe trigger some other events
    */
});

jQuery의 DOM 중심 접근 방식 이벤트는 DOM 요소에 게시됩니다. 일반 이벤트의 창 또는 문서 객체이거나 선택기를 사용하여 jQuery 객체를 생성 할 수 있습니다. 데모로 취한 접근 방식은 구독자를 정의하는 거의 네임 스페이스 방식을 만드는 것입니다.

가입자가 될 DOM 요소는 "구독자"및 "networkDetection"으로 간단히 분류됩니다. 그런 다음 알림 이벤트를 트리거하여 이러한 요소 (데모에 하나만있는)에만 이벤트를 게시 할 수 있습니다.$(“.subscriber.networkDetection”)

#notifier의 일부 사업부 .subscriber.networkDetection가입자 그룹은 효과적으로 청취자의 역할을 바인드 익명의 기능이 있습니다.

$('#notifier').bind("notify.networkDetection",function(e, online){
    // the following simply demonstrates
    notifier = $(this);
    if(online){
        if (!notifier.hasClass("online")){
            $(this)
                .addClass("online")
                .removeClass("offline")
                .text("ONLINE");
        }
    }else{
        if (!notifier.hasClass("offline")){
            $(this)
                .addClass("offline")
                .removeClass("online")
                .text("OFFLINE");
        }
    };
});

그래서 당신은 간다. 그것은 모두 장황하고 내 예제는 전혀 흥미 롭지 않습니다. 또한이 방법으로 할 수있는 흥미로운 것을 보여주지는 않지만 소스를 파고 싶은 사람이 있다면 자유롭게 느끼십시오. 모든 코드는 데모 페이지 헤드에 인라인되어 있습니다.


내가 찾던 것입니다. 그는 아마도 그것이 갈 길이라고 생각할 수도 있지만 jquery가 직접 지원하거나 플러그인을보다 우아하게 처리해야한다고 생각할 수는 없습니다. 답변을 표시하기 전에 조금 기다렸다가 문제에 대한 다른
조치가 있는지 확인해 보겠습니다.

6
어딘가에서 인용 한 것입니까? 그렇다면, 출처를 인용하고 링크가 존재하는 경우 링크를 제공하십시오.
Aryeh Leib Taurog

1
예, 편집 기록 에서이 링크입니다 . 현재 액세스 할 수 없습니다. 보관 된 페이지는 여기에 있습니다 .
Stano

1
Ben Alman 은 작은 (작은 작은) jQuery pub sub plugin을 작성했습니다 . 매우 우아합니다.
바니

127

허용 된 답변에 제공된 링크는 jQuery를 사용하여 pub / sub 시스템 을 구현하는 좋은 방법을 보여 주지만 코드를 읽는 것이 다소 어렵다는 것을 알았으므로 여기에 간단한 코드 버전이 있습니다.

http://jsfiddle.net/tFw89/5/

$(document).on('testEvent', function(e, eventInfo) { 
  subscribers = $('.subscribers-testEvent');
  subscribers.trigger('testEventHandler', [eventInfo]);
});

$('#myButton').on('click', function() {
  $(document).trigger('testEvent', [1011]);
});

$('#notifier1').on('testEventHandler', function(e, eventInfo) { 
  alert('(notifier1)The value of eventInfo is: ' + eventInfo);
});

$('#notifier2').on('testEventHandler', function(e, eventInfo) { 
  alert('(notifier2)The value of eventInfo is: ' + eventInfo);
});

10
이 답변이 정말 마음에 듭니다. 누구나 trigger () bind () (및 on ()) 문서를 읽을 수 있지만이 답변은 jquery를 사용하여 이벤트 버스 (pub / sub 시스템)를 작성하는 구체적인 예를 제공합니다.
lostdorje

1
브라보. 내가 알아야 할 모든 것.
패트릭 피셔

사용자 정의 이벤트를 트리거 할 때 배열 (길이> 1)을 전달하면 리스너는 인수의 모든 배열 항목을 가져 와서 n여러 인수로 끝납니다 .
vsync

리스너에서 여러 인수 처리에 대한 솔루션 :var eventData = [].slice.call(arguments).splice(1)
vsync

2
#notifier dummy 요소없이이 작업을 수행 할 수있는 방법이 있습니까? 자바 스크립트 라이브러리가 있고 객체가 이벤트를 노출하기를 원한다면 페이지에 어떤 요소가 있는지 확신 할 수 없습니다.
AaronLS

21

나는 그렇게 생각한다. 다음과 같이 커스텀 이벤트를 '바인딩'하는 것이 가능하다 : ( http://docs.jquery.com/Events/bind#typedatafn ) :

 $("p").bind("myCustomEvent", function(e, myName, myValue){
      $(this).text(myName + ", hi there!");
      $("span").stop().css("opacity", 1)
               .text("myName = " + myName)
               .fadeIn(30).fadeOut(1000);
    });
    $("button").click(function () {
      $("p").trigger("myCustomEvent", [ "John" ]);
    });

1
이벤트를 제기하고 가입자 / 청취 인이 트리거하는 방법을 찾고 있습니다. 올리는 대상이 누가 듣고 있는지 모르기 때문에 수동으로 트리거하지 마십시오.
Per Hornshøj-Schierbeck

2
이 코드는 그렇지 않습니까? myCustomEvent발생하면 상단의 바인드에 리스너가 추가됩니다.
스프린트 스타

15

비슷한 질문이 있었지만 실제로는 다른 대답을 찾고있었습니다. 맞춤 이벤트를 만들려고합니다. 예를 들어 항상 이것을 말하는 대신 :

$('#myInput').keydown(function(ev) {
    if (ev.which == 13) {
        ev.preventDefault();
        // Do some stuff that handles the enter key
    }
});

나는 이것을 다음과 같이 요약하고 싶다 :

$('#myInput').enterKey(function() {
    // Do some stuff that handles the enter key
});

트리거 및 바인딩은 전체 스토리를 알려주지 않습니다. 이것은 JQuery 플러그인입니다. http://docs.jquery.com/Plugins/Authoring

"enterKey"함수는 jQuery.fn에 속성으로 첨부됩니다. 이것은 필수 코드입니다.

(function($){
    $('body').on('keydown', 'input', function(ev) {
        if (ev.which == 13) {
            var enterEv = $.extend({}, ev, { type: 'enterKey' });
            return $(ev.target).trigger(enterEv);
        }
    });

    $.fn.enterKey = function(selector, data, fn) {
        return this.on('enterKey', selector, data, fn);
    };
})(jQuery);

http://jsfiddle.net/b9chris/CkvuJ/4/

위의 장점 중 하나는 다음과 같은 링크 리스너에서 키보드 입력을 정상적으로 처리 할 수 ​​있다는 것입니다.

$('a.button').on('click enterKey', function(ev) {
    ev.preventDefault();
    ...
});

편집 : 올바른 this컨텍스트를 처리기 에 올바르게 전달하고 처리기에서 jQuery로 반환 값을 다시 반환하도록 업데이트되었습니다 (예 : 이벤트를 취소하고 버블 링하려는 경우). 키 코드 및 이벤트 취소 기능을 포함하여 적절한 jQuery 이벤트 객체를 핸들러에 전달하도록 업데이트되었습니다.

이전 jsfiddle : http://jsfiddle.net/b9chris/VwEb9/24/


Chris-함수가 완벽하게 작동했습니다. 작동하지 않는 유일한 것은이 변수에 액세스하는 것입니다. e.currentTarget을 사용하여 액세스 할 수 있지만 더 효율적인 방법이 있는지 궁금합니다.
Addy

그 버그를 잘 잡아라. 예, handler (ev)에서 5 행을 변경하면; to : handler.call (this, ev); 이 인수는 일반적으로 표준 jquery 이벤트 핸들러와 동일합니다. jsfiddle.net/b9chris/VwEb9
Chris Moschini

다른 방법으로 이것을 구현하는 방법도 알고 있습니까? 이 예제를 사용하려고하지만와 함께 scroll전파하지는 않습니다. 리스너를 본문에 하드 코딩하는 대신 on이벤트 자체를 발생시키기 위해 -event가 바인딩 된 요소가 필요하다고 생각합니다 .
Gust van de Wal

나는 당신이 요구하는 시나리오를 확신하지 못한다. 코드 샘플과 함께 질문하는 것이 가장 좋습니다.
Chris Moschini

9

오래된 게시물이지만 새로운 정보로 업데이트하려고합니다.

사용자 정의 이벤트를 사용하려면 일부 DOM 요소에 바인딩하고 트리거해야합니다. 그래서 당신은 사용해야합니다

.on () 메소드는 이벤트 유형 및 이벤트 처리 기능을 인수로 사용합니다. 선택적으로 이벤트 관련 데이터를 두 번째 인수로 수신하여 이벤트 처리 기능을 세 번째 인수로 푸시 할 수도 있습니다. 전달 된 모든 데이터는 이벤트 객체의 data 속성에서 이벤트 처리 기능에 사용할 수 있습니다. 이벤트 처리 함수는 항상 첫 번째 인수로 이벤트 객체를받습니다.

.trigger () 메소드는 이벤트 유형을 인수로 사용합니다. 선택적으로 값 배열을 취할 수도 있습니다. 이 값은 이벤트 객체 다음에 인수로 이벤트 처리 함수에 전달됩니다.

코드는 다음과 같습니다.

$(document).on("getMsg", {
    msg: "Hello to everyone",
    time: new Date()
}, function(e, param) {
    console.log( e.data.msg );
    console.log( e.data.time );
    console.log( param );
});

$( document ).trigger("getMsg", [ "Hello guys"] );

여기여기에 좋은 설명이 있습니다 . 이것이 정확히 유용한 이유는 무엇입니까? 트위터 엔지니어로부터이 훌륭한 설명에 그것을 사용하는 방법을 찾았습니다 .

PS 일반 자바 스크립트에서는 새로운 CustomEvent 로이 작업을 수행 할 수 있지만 IE 및 Safari 문제에주의하십시오.


3

맞춤 이벤트를 작성하는 방법은 다음과 같습니다.

var event = jQuery.Event('customEventName');
$(element).trigger(event);

물론, 당신은 단순히 할 수 있습니다

$(element).trigger('eventname');

그러나 내가 쓴 방법을 사용하면 사용자가 기본값을 막았는지 여부를 감지 할 수 있습니다

var prevented = event.isDefaultPrevented();

이를 통해 최종 사용자의 요청을 듣고 특정 이벤트 처리를 중지 할 수 있습니다 (예 : 양식에서 단추 요소를 클릭하지만 오류가있는 경우 양식을 게시하지 않으려는 경우).


나는 보통 다음과 같은 사건을 듣는다

$(element).off('eventname.namespace').on('eventname.namespace', function () {
    ...
});

다시 한번, 당신은 할 수 있습니다

$(element).on('eventname', function () {
    ...
});

그러나 특히 팀에서 일하는 경우 항상 다소 안전하지 않은 것으로 나타났습니다.

다음에는 아무런 문제가 없습니다.

$(element).on('eventname', function () {});

그러나 어떤 이유로 든이 이벤트를 바인딩 해제해야한다고 가정합니다 (비활성화 된 버튼을 상상하십시오). 그때해야 할 것

$(element).off('eventname', function () {});

eventname에서 모든 이벤트 가 제거 됩니다 $(element). 미래에 누군가가 이벤트를 해당 요소에 바인딩할지 여부를 알 수 없으며 실수로 해당 이벤트를 바인딩 해제합니다

이를 피하는 안전한 방법은 이벤트를 네임 스페이스로 수행하는 것입니다.

$(element).on('eventname.namespace', function () {});

마지막으로, 첫 번째 줄이

$(element).off('eventname.namespace').on('eventname.namespace', ...)

나는 개인적으로 항상 바인딩을 해제 이벤트를 바인딩 단지 확인 동일한 이벤트 핸들러가 호출되지 없구요 것을 여러 번 할 전에 (상상이는이 지불 양식에 버튼을 제출했다 이벤트는 5 회를 구속했다)


좋은 접근. 네임 스페이스의 경우 +1
Aurovrata
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.