/Hàm bind trong JQuery API

Hàm bind trong JQuery API

Hàm bind là một trong các hàm hỗ trợ sẵn (built-in fuctions) JQuery API của thư viện jQuery được sử dụng để gắn một bộ xử lý sự kiện cho các phần tử được chọn.

1. Cú pháp hàm bind

Các cú pháp:

$(selector).bind(eventType [, eventData ], handler);

$(selector).bind(eventType [, eventData ] [, preventBubble ]);

$(selector).bind(events);

Tham số:

  • selector: Một chuỗi chứa tên của một hoặc nhiều loại sự kiện DOM, ví dụ: “click”, “submit”, hoặc tên tùy chỉnh của sự kiện.
  • eventType: Loại sự kiện (tương tự như selector).
  • eventData: Dữ liệu gửi cùng với sự kiện.
  • handler: Một hàm để thực thi khi sự kiện xảy ra.
  • preventBubble: Kiểu boolean, true mặc định, ngăn sự kiện bong bóng và hành động mặc định.
  • events: Đối tượng chứa một hoặc nhiều loại sự kiện và các hàm tương ứng.

Kiểu dữ liệu trả về:

  • Không trả về giá trị.

Phiên bản:

  • .bind(eventType [, eventData ], handler): jQuery 1.0
  • .bind(eventType [, eventData ] [, preventBubble ]): jQuery 1.4.3
  • .bind(events): jQuery 1.4

Những chú ý:

  • .bind() đã được ghi đè bởi phương thức .on() trong jQuery 1.7, nên khuyến cáo không sử dụng .bind() mà sử dụng .on().
  • Nếu eventType chứa dấu chấm (.), sự kiện sẽ có namespace, cho phép ta unbind hoặc trigger một số sự kiện mà không làm ảnh hưởng đến những sự kiện khác.

Hàm bind giờ đã bị khuyến nghị không sử dụng, thay vào đó bạn nên sử dụng hàm on để gắn sự kiện.

Hàm bind trong JQuery API

2. Sự kiện (event) trong DOM

Sự kiện (event) trong DOM (Document Object Model) đề cập đến các hành vi, tương tác và thay đổi trạng thái xảy ra trên trang web hoặc ứng dụng web khi người dùng tương tác với các phần tử HTML. Đây có thể là hành động như nhấp chuột, kéo và thả, gõ phím, thay đổi kích thước cửa sổ, và nhiều hành động khác.

Khi người dùng tương tác với trang web, các sự kiện xảy ra và được gửi đến các phần tử trong DOM. Ví dụ, khi người dùng nhấp chuột vào một nút (button), sự kiện “click” sẽ được tạo ra và gửi đến phần tử đó.

Các sự kiện trong DOM cung cấp cơ chế cho phép lắng nghe và xử lý tương tác của người dùng, làm cho trang web trở nên tương tác và linh hoạt hơn.

jQuery hỗ trợ các sự kiện chuẩn của DOM như blur, focus, load, resize, scroll, unload, beforeunload, click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave, change, select, submit, keydown, keypress, và keyup.

Thư viện jQuery cho phép kích hoạt sự kiện bằng bất kỳ tên nào trên một phần tử và sự kiện này được lan truyền lên cây DOM mà phần tử đó thuộc về.

3. Một số ví dụ hàm bind

3.1. Sử dụng để tạo game đập chuột

Dưới đây là một ví dụ nâng cấp sử dụng hàm bind với các tham số : eventType, handler để tạo một trò chơi đập chuột (whack-a-mole game) đơn giản.

Trong trò chơi này, khi chuột xuất hiện (mói), người chơi cần nhấp chuột vào nó để ghi điểm.

HTML Code:

<!DOCTYPE html>
<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
 <style>
    .hole {
      width: 50px;
      height: 50px;
      border: 1px solid #000;
      display: inline-block;
      margin: 5px;
      cursor: pointer;
      background-color: #ccc;
      position: relative;
    }

    .mole {
      background-color: brown;
      display: none;
      width: 100%;
      height: 100%;
      border-radius: 50%;
      position: absolute;
      top: 0;
      left: 0;
    }

    .label {
      margin-top: 20px;
      font-size: 18px;
      font-weight: bold;
    }
  </style>
</head>
<body>

<h1>Whack-a-Mole Game</h1>
<p>Click the moles as they appear!</p>

<button onclick="startGame()" id="startButton">Start Game</button>

<div id="gameArea" style="display: none;">
  <div class="hole"><div class="mole"></div></div>
  <div class="hole"><div class="mole"></div></div>
  <div class="hole"><div class="mole"></div></div>
  <div class="hole"><div class="mole"></div></div>
  <div class="hole"><div class="mole"></div></div>
  <div class="hole"><div class="mole"></div></div>
  <div class="hole"><div class="mole"></div></div>
  <div class="hole"><div class="mole"></div></div>
  <div class="hole"><div class="mole"></div></div>
  <div class="hole"><div class="mole"></div></div>
  <div class="hole"><div class="mole"></div></div>
  <div class="hole"><div class="mole"></div></div>
</div>

<div class="label">Time remaining: <span id="timeRemaining">30</span> seconds</div>

<div id="score">Score: 0</div>

<script>
let score = 0;
let timeRemaining = 30;
let gameInterval;
let moleInterval;
let gameRunning = false;

function updateScore() {
    $('#score').text('Score: ' + score);
}

function updateTimer() {
    $('#timeRemaining').text(timeRemaining);
}

function moleClick(event) {
    if ($(this).find('.mole').is(':visible')) {
        score++;
        updateScore();
        $(this).find('.mole').hide();
    }
}

function showMole() {
    $('.hole .mole').hide();
    const randomIndex = Math.floor(Math.random() * 12);
    const hole = $('.hole').eq(randomIndex);
    const holeWidth = hole.width();
    const mole = hole.find('.mole');
    mole.css('width', holeWidth + 'px');
    mole.css('height', holeWidth + 'px');
    mole.css('border-radius', holeWidth / 2 + 'px');
    mole.show();
}

function endGame() {
    $('#startButton').prop('disabled', false);
    clearInterval(gameInterval);
    clearInterval(moleInterval);
    gameRunning = false;

    let message = '';
    if (score >= 25) {
        message = 'Excellent performance! Score: ' + score;
        $('.label').css('color', 'green');
    } else if (score >= 20) {
        message = 'Great job! Score: ' + score;
        $('.label').css('color', 'yellow');
    } else if (score >= 15) {
        message = 'You completed the game! Score: ' + score;
        $('.label').css('color', 'blue');
    } else {
        message = 'Game Over! Score: ' + score;
        $('.label').css('color', 'red');
    }

    $('.label').text(message);
}

function startGame() {
    score = 0;
    timeRemaining = 30;
    updateScore();
    updateTimer();
    $('#gameArea').show();
    $('.hole').bind('click', moleClick);

    $('#startButton').prop('disabled', true);

    gameRunning = true;
    gameInterval = setInterval(function() {
        timeRemaining--;
        updateTimer();
        if (timeRemaining <= 0 && gameRunning) {
            endGame();
        }
    }, 1000);

    moleInterval = setInterval(showMole, 1000);
}
</script>

</body>
</html>

Trong ví dụ này, có 12 lỗ, và con chuột sẽ xuất hiện ngẫu nhiên ở các lỗ sau mỗi giây. Điểm được ghi nhận khi người dùng thực hiện thao tác click trúng con chuột khi nó xuất hiện ở các lỗ.

Trò chơi diễn ra trong 30 giây, mỗi lần đập trúng bạn sẽ ghi được 1 điểm và nếu bạn đập trúng trên 15 con bạn sẽ chiến thắng ngược lại bạn sẽ thua.

3.2. Nâng cấp trò chơi đập chuột với eventData

Ở ví dụ này chúng ta nâng cấp trò chơi ở ví dụ trước bằng cách thêm dữ liệu cho hàm bind thông qua eventData, lúc này mỗi con chuột xuất hiện sẽ có điểm ngẫu nhiên từ 1 tới 3.

Nâng cấp ví dụ trước ở 2 hàm như sau:

function showMole() {
    $('.hole .mole').hide();
    const randomIndex = Math.floor(Math.random() * 12);
    const hole = $('.hole').eq(randomIndex);
    const holeWidth = hole.width();
    const mole = hole.find('.mole');

    const randomScore = Math.floor(Math.random() * 3) + 1;
    mole.data('score', randomScore);

    mole.css('width', holeWidth + 'px');
    mole.css('height', holeWidth + 'px');
    mole.css('border-radius', holeWidth / 2 + 'px');
    mole.text(randomScore);
    mole.show();

    // Bind the click event with eventData (the mole's score)
    hole.unbind('click').bind('click', { score: randomScore }, moleClick);
}

function moleClick(event) {
    const moleScore = event.data.score;

    if ($(this).find('.mole').is(':visible')) {
        score += moleScore;
        updateScore();
        $(this).find('.mole').hide();
    }
}

Khi người dùng đập đúng con chuột thì lúc đó số điểm được cộng sẽ là số điểm con chuột có thay vì chỉ tăng thêm một như ở ví dụ trước.

3.3. Sử dụng preventBubble

Việc thiết lập tham số preventBubble được sử dụng để ngăn chặn hành động mặc định của sự kiện và ngăn chặn khỏi việc lan truyền lên các phần tử cha.

  • Khi preventBubble được đặt thành true (mặc định), sự kiện sẽ được xử lý theo cách thông thường và có thể lan truyền lên các phần tử cha của phần tử gốc.
  • Khi preventBubble được đặt thành false, sự kiện không chỉ bị ngăn chặn khỏi việc lan truyền lên các phần tử cha, mà còn ngăn chặn hành động mặc định của sự kiện
<!DOCTYPE html>
<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>

<div class="parent1" style="background-color: lightblue; padding: 20px;"> Parent div 1
  <div class="child1" style="background-color: lightgreen; padding: 10px;">
    Click me without preventBubble
  </div>
</div>

<div class="parent2" style="background-color: lightcoral; padding: 20px;"> Parent div 2
  <div class="child2" style="background-color: lightsalmon; padding: 10px;">
    Click me with preventBubble
  </div>
</div>

<div class="parent3" style="background-color: lightblue; padding: 20px;"> Parent div 3
  <div class="child3" style="background-color: lightgreen; padding: 10px;">
    Click me with preventBubble by function
  </div>
</div>

<script>
$(document).ready(function(){
  $(".child1").bind( "click", function() {
  alert( $( this ).text() );
});

  $(".child2").bind( "click", function() {
  alert( $( this ).text() );
	},false);
	
	 $(".child3").bind( "click", function() {
  alert( $( this ).text() );
	},function(){return false;});
});
</script>

</body>
</html>

3.4. Tác dụng của stopPropagation

Ngăn chặn lan truyền sự kiện lên các phần tử cha (stopPropagation) nghĩa là khi một sự kiện xảy ra trên một phần tử con, thì thông thường sự kiện đó sẽ “lan truyền” lên các phần tử cha của phần tử con đó.

Nhưng trong một số trường hợp, chúng ta muốn ngăn chặn sự kiện đó không lan truyền lên các phần tử cha. Điều này có thể hữu ích khi chúng ta muốn xử lý sự kiện chỉ trên phần tử hiện tại mà không ảnh hưởng đến các phần tử cha.

HTML Code:

<!DOCTYPE html>
<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
  <style>
    .parent {
      padding: 20px;
      margin: 10px;
      border: 1px solid #000;
    }
    .child {
      padding: 10px;
      margin: 5px;
      border: 1px solid #ccc;
      cursor: pointer;
    }
  </style>
</head>
<body>

<div class="parent" id="parent1">
  Parent 1
  <div class="child" id="child1">
    Child 1 - Click me!
  </div>
</div>

<div class="parent" id="parent2">
  Parent 2
  <div class="child" id="child2">
    Child 2 - Click me!
  </div>
</div>

<script>
$(document).ready(function(){
  $("#child1").bind("click", function(event){
    alert("Clicked on child element: " + this.id);
  });
  
  $("#child2").bind("click", function(event){
    alert("Clicked on child element: " + this.id);
	event.stopPropagation();
  });

  $("#parent1").bind("click", function(event){
    alert("Clicked on parent element: " + this.id);
  });

  $("#parent2").bind("click", function(event){
    alert("Clicked on parent element: " + this.id);
  });
});
</script>

</body>
</html>

Trong ví dụ này, khi bạn click vào một phần tử con (child), sự kiện click sẽ lan truyền lên các phần tử cha của nó. Nếu bạn muốn ngăn chặn sự kiện này không lan truyền lên các phần tử cha, bạn có thể sử dụng event.stopPropagation().

3.5. Tác dụng của preventDefault

Ngăn chặn hành động mặc định (event.preventDefault()) trong sự kiện Javascript có nghĩa là ngăn chặn hành vi mặc định mà trình duyệt thực hiện khi xảy ra một sự kiện. Ví dụ phổ biến là ngăn chặn trình duyệt tải lại trang khi người dùng click vào một liên kết.

Dưới đây là một ví dụ đơn giản:

HTML Code:

<!DOCTYPE html>
<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</head>
<body>

<a href="https://www.example.com" id="myLink">Click me to prevent default</a>

<script>
$(document).ready(function(){
  $("#myLink").bind("click", function(event){
    event.preventDefault();  // Ngăn chặn hành động mặc định của liên kết
    alert("Default action prevented. You clicked a link, but the page was not reloaded.");
  });
});
</script>

</body>
</html>

Khi bạn click vào liên kết “Click me to prevent default”, sự kiện click được xử lý, và hàm event.preventDefault() ngăn chặn trình duyệt tải lại trang, thay vào đó hiển thị một cửa sổ cảnh báo. Điều này đảm bảo rằng trang web không bị tải lại sau khi click vào liên kết.

3.6. Dùng bind để add nhiều sự kiện

Cả hai cách sử dụng hàm bind đều dùng để gắn các sự kiện (event) vào một đối tượng. Cả hai đều cho phép bạn thực hiện một hành động khi sự kiện xảy ra trên đối tượng đó.

Sự khác biệt chủ yếu giữa chúng là cú pháp và cách truyền các sự kiện.

<!DOCTYPE html>
<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <style>
    .box {
      width: 100px;
      height: 100px;
      background-color: lightblue;
      margin: 20px;
      text-align: center;
      line-height: 100px;
      cursor: pointer;
    }
  </style>
</head>
<body>

<div class="box" id="box1">Multiple binds</div>
<div class="box" id="box2">Single bind</div>

<script>
$(document).ready(function(){
  $("#box1")
    .bind("click", function(){
      alert($(this).text());
    })
    .bind("mouseenter", function(){
      $(this).css("background-color", "red");
    })
    .bind("mouseleave", function(){
      $(this).css("background-color", "lightblue");
    });

  $("#box2").bind({
    click: function(){
      alert($(this).text());
    },
    mouseenter: function(){
      $(this).css("background-color", "red");
    },
    mouseleave: function(){
      $(this).css("background-color", "lightblue");
    }
  });
});
</script>

</body>
</html>

Dù sử dụng cách nào, cả hai đều cho phép bạn gắn sự kiện vào đối tượng và xử lý các sự kiện đó khi chúng xảy ra. Tuy nhiên, cách sử dụng một lần với đối tượng JavaScript có thể làm mã của bạn gọn hơn và dễ quản lý khi bạn muốn gắn nhiều sự kiện cùng một lúc.