Thứ Hai, 7 tháng 12, 2015

Tìm hiểu về event trong jQuery

jQuerry làm cho việc tương tác của user trên trang trở nên dễ dàng hơn bao giờ hết. Có nghĩa là bạn có thể viết code chạy song song với khi user click vào một thành phần nào đó của trang web, hoặc khi user di chuyển chuột trên một form element. Ví dụ, đoạn code này giúp ta lắng nghe sự kiện khi user click vào bất cứ element li nào trên trang web:
  $( 'li' ).click(function( event ) {
     console.log( 'clicked', $( this ).text() );
  });
Đoạn code trên chọn tất cả list item trên trang, sau đó bind một handler function (hàm xử lý sự kiện) với sự kiện click của mỗi list item sử dụng method .click() của jQuerry
Các methods như .click().blur().change() và những cái khác là các methods "shorthand" cho sự kiện binding. jQuery cung cấp một số các methods shorthand, mỗi một method trong đó tương ứng với một native DOM event
Native Event NameShorthand Method
click.click()
keydown.keydown()
keypress.keypress()
keyup.keyup()
mouseover.mouseover()
mouseout.mouseout()
mouseenter.mouseenter()
mouseleave.mouseleave()
scroll.scroll()
focus.focus()
blur.blur()
resize.resize()
Tất cả các methods shorthand đều được sử dụng thông qua method .on() của jQuery. Bạn có thể sử dụng method .on() trong code của mình và thực sự nó cho bạn nhiều sự linh hoạt hơn. Khi sử dụng method .on(), bạn truyền native event name vào như đối số đầu tiên, và handler function là đối số thứ hai:
  $( 'li' ).on( 'click', function( event ) {
    console.log( 'clicked', $( this ).text() );
  });
Một khi đã bind 1 event handler vào một element, bạn có thể kích hoạt event handler đó sử dụng jQuerry
  $( 'li' ).trigger( 'click' );
Nếu event bạn muốn kích hoạt có method shorthand (xem bảng trên), bạn cũng có thể kích hoạt event đó chỉ bằng cách gọi method shorthand:
  $( 'li' ).click();
Khi .trigger() một event, bạn chỉ kích hoạt event handlers đã được bound với JavaScript - bạn không kích hoạt các hành vi mặc định của event. Ví dụ, nếu bạn kích hoạt event click của element a, nó sẽ không tự động điều hướng đến href của element đó (mặc dù bạn có thể viết code để làm điều đó).
Một khi đã bound một event, bạn có thể unbind event sử dụng method .off() của jQuery. Nó sẽ loại bỏ bất cứ event handlers nào được bound với các event cụ thể:
  $( 'li' ).off( 'click' );

Namespaced events

Một lợi thế mà .on() cung cấp là khả năng sử dụng "namespaced" events. Khi nào bạn muốn sử dụng namespaces? Hãy xem xét một tình huống khi bạn bind một số events, và sau đó muốn unbind một số events của handlers. Bạn có thể làm theo cách này:
  $( 'li' ).on( 'click', function() {
    console.log( 'a list item was clicked' );
  });

  $( 'li' ).on( 'click', function() {
    registerClick();
    doSomethingElse();
  });

  $( 'li' ).off( 'click' );
Tuy nhiên, nó sẽ unbind tất cả click handlers trên tất cả các elements li, đó không phải là những gì chúng ta muốn. Nếu bạn bind một event handler sử dụng namespaced event, bạn có thể xác định event handler đó một cách cụ thể
  $( 'li' ).on( 'click.logging', function() {
    console.log( 'a list item was clicked' );
  });

  $( 'li' ).on( 'click.analytics', function() {
    registerClick();
    doSomethingElse();
  });

  $( 'li' ).off( 'click.logging' );
Code này để lại cho ta các phân tích có liên quan đến click untouched, trong khi unbinding logging-related click.
Chúng ta cũng có thể sử dụng namespaces để kích hoạt các events nhất định:
  $( 'li' ).trigger( 'click.logging' );

Binding nhiều events một lúc

Một lợi ích khác của việc sử dụng .on() là khả năng bind nhiều events một lúc. Ví dụ, bạn muốn chạy cùng một đoạn code khi users scroll windows hoặc khi user resizes windows. Method.on() cho phép bạn truyền vào cả hai sự kiện, hãy xem ví dụ sau:
  $( 'input[type="text"]' ).on('focus blur', function() {
    console.log( 'The user focused or blurred the input' );
  });

  $( window ).on( 'resize.foo scroll.bar', function() {
    console.log( 'The window has been resized or scrolled!' );
  });

Truyền hàm callback như 1 tham số để handler event

Trong các ví dụ trên, chúng tôi đã truyền các anonymous functions vào như event handlers. Tuy nhiên, bạn có thể tạo trước một function và lưu nó trong một biến, sau đó truyền biến này vào như event handlers. Điều này rất hữu ích nếu bạn muốn sử dụng cùng một handler cho các events khác nhau hoặc các events trên các elements khác nhau
  var handleClick = function() {
    console.log( 'something was clicked' );
  };

  $( 'li' ).on( 'click', handleClick );
  $( 'h1' ).on( 'click', handleClick );

Event object

Bất cứ khi nào một event được kích hoạt, hàm callback của nó sẽ bắn ra 1 object. Đối tượng này có nhiều thuộc tính hữu ích, bao gồm
  $( document ).on( 'click', function( event ) {
    console.log( event.type );    // The event type, eg. "click"
    console.log( event.which );   // The button or key that was pressed.
    console.log( event.target );  // The originating element.
    console.log( event.pageX );   // The document mouse X coordinate.
    console.log( event.pageY );   // The document mouse Y coordinate.
  });

Bên trong event handler

Khi bạn chỉ định một function được sử dụng như một event handler, function đó được quyền truy cập vào raw DOM element bắt đầu event là this. Nếu bạn muốn sử dụng jQuery để thao tác với element, bạn cần truyền nó vào $():
  $( 'input' ).on( 'keydown', function( event ) {
    // this: The element on which the event handler was bound.
    // event: The event object.

    // Change the input element's background to red if backspace was
    // pressed, otherwise green.
    $( this ).css( 'background', event.which === 8 ? 'red' : 'green' );
  });

PreventDefault

Thông thường, bạn sẽ muốn ngăn chặn các hành động mặc định của một event; Ví dụ, bạn muốn xử lý click trên một thẻ a sau đó sử dụng AJAX nhưng không muốn reload lại trang. Nhiều developers xử lý bằng trả về false trong function handler, cách này cũng ok nhưng nó sẽ stop event bubbling từ các thành phần cha . Cách đúng đắn để ngăn chặn hành vi mặc định của một event là gọi method .preventDefault() của event object.
  $( 'a' ).on( 'click', function( event ) {
    // Prevent the default action.
    event.preventDefault();
    // Log stuff.
    console.log( 'I was just clicked!' );
  });
Nó sẽ cho phép event “bubble”, khái niệm mà ta sẽ tìm hiểu ngay sau đây.

Event bubbling

Hãy xem xét đoạn code sau
  $( '*' ).add( [ document, window ] ).on( 'click', function( event ) {
    event.preventDefault();
    console.log( this );
  });
Nó bind một click handler cho các elements trong document (một vài điều bạn đừng nên làm trong code của mình), cũng như document và window. Điều gì xảy ra khi bạn click vào element a được đặt bên trong các elements khác? Trong thực tế, click event sẽ được kích hoạt cho element a cũng như cho tất cả các elements khác có chứa thẻ a đó – mọi cách đều phụ thuộc vào document và window.
Hành vi này được gọi là event bubbling - event được kích hoạt trên element mà user click vào, và trừ khi bạn gọi .stopPropagation() trên event object.
Bạn có thể thấy điều này rõ ràng hơn khi xem markup sau
  <a href="#foo"><span>I am a Link!</span></a>
  <a href="#bar"><b><i>I am another Link!</i></b></a>
Và code sau
  $( 'a' ).on( 'click', function( event ) {
    event.preventDefault();
    console.log( $( this ).attr( 'href' ) );
  });
Khi bạn click vào "I am a Link!", bạn không thực sự click vào a mà là bạn đang vào thẻ span bên trong của a. Vì thẻ span nằm trong thẻ a nên cũng sẽ có 1 event gắn vào nó, nếu bạn chỉ muốn handler event trên thẻ span mà không muốn cái event từ thẻ a ảnh hưởng đến hãy sử dụng.stopPropagation, xem đoạn code sau:
  $( 'span' ).on( 'click', function( event ) {
     event.stopPropagation();
     console.log( 'wtf' );
  });

Event delegation

Hành vi bubbling của các events cho phép chúng ta thực hiện "event delegation" – binding handlers cho các elements cấp cao, sau đó phát hiện ra element cấp thấp nào khởi đầu event. Ví dụ, chúng ta có thể bind một event vào một unordered list, sau đó xác định element nào khởi đầu event:
  $( '#my-unordered-list' ).on( 'click', function( event ) {
    console.log( event.target ); // logs the element that initiated the event
  });
Tất nhiên, nếu unordered list của chúng ta bao gồm list items có chứa các markup khác, nhưng chúng ta chỉ thực sự quan tâm đến việc list item nào được click, thì sự việc sẽ trở nên rối tung rối mù. May mắn thay, jQuery cung cấp một helper cho phép chúng ta xác định những elements nào mình quan tâm, trong khi vẫn binding nó với các element cấp cao
  $( '#my-unordered-list' ).on( 'click', 'li', function( event ) {
    console.log( this ); // logs the list item that was clicked
  });

  $( '<li>a new list item!</li>' ).appendTo( '#my-unordered-list' );
Event delegation có hai lợi ích chính.
  • Đầu tiên, nó cho phép chúng ta bind các event handlers ít hơn so với bình thường nếu ta đang lắng nghe click trên các elements riêng, việc làm này có thể tối ưu hiệu năng xử lý javascript của trình duyệt.
  • Thứ hai, nó cho phép chúng ta bind các elements parent cho phép nó listen ngay khi nội dung DOM thay đổi.
Ví dụ, đoạn code này add một list items mới sau khi event delegation được thiết lập; việc click vào item mới hoạt động tốt mà không có thêm bất kỳ event binding code nào
  $( '#my-unordered-list' ).on( 'click', 'li', function( event ) {
    console.log( this ); // logs the list item that was clicked
  });

  $( '<li>a new list item!</li>' ).appendTo( '#my-unordered-list' );

Kết luận

Trong phần này, chúng ta đã tìm hiểu những cách khác nhau để listen và handler hành vi của user khi họ tương tác với trang của mình, bao gồm cách chúng ta sử dụng event delegation để thiết lập event handlers một cách hiệu quả hơn. Trong phần tiếp theo, chúng ta sẽ tìm hiểu về các hiệu ứng trong jQuery.
Editor: Justin Luong
Translator: Trần Tuấn Dũng
Sưu tầm từ: http://fsd14.com/post/82-jquery-co-ban-phan-3-tim-hieu-ve-event-trong-jquery

Không có nhận xét nào:

Đăng nhận xét