Hướng dẫn for each button click javascript - cho mỗi nút nhấp vào javascript
Tôi đang tạo một trò chơi đơn giản cho một dự án và cần giá trị tương ứng của mỗi nút để được hiển thị trong đầu vào khi nhấp. Show
Tôi có thể sử dụng thành công "getEuityByid" với JS sau:
Tất nhiên tôi có thể lặp lại mã này cho tất cả các nút 0-9 nhưng tôi muốn sử dụng "vòng lặp" nếu có thể thực hiện điều này chỉ với một khối mã. Tôi đã thực hiện nỗ lực sau đây bằng cách chỉ cố gắng mô phỏng mã trên hoạt động cho một "id" và chỉ cần chuyển ra "nút1" cho một vòng lặp qua "nút" (tôi đã thử cả "QuerySelectorall" và "getElementsByClassName"). Tôi nhận được lỗi: "Nút.AdDeventListener không phải là một hàm." Tôi không hiểu vì trong mã nút đơn thành công "nút1.AddeventListener (" Nhấp ", hàm (e)" cũng không phải là một hàm nhưng nó hoạt động ... bên dưới là lần thử vòng lặp, theo sau là toàn bộ trang: 48,475 Khi bạn đính kèm nhiều sự kiện nhấp vào các phần tử như các nút bên trong A For Loop, sự kiện nhấp sẽ luôn cung cấp cho chúng tôi giá trị LastIndex bất kể nhấn nút nào.elements such as buttons inside a for loop, the click event will always give us the last index value regardless of what button is pressed. Đây là một trong những vấn đề phổ biến mà các nhà phát triển gặp phải khi họ bắt đầu học JavaScript. Đến cuối bài viết này, bạn sẽ biết nguyên nhân gây ra vấn đề này và một số cách để khắc phục nó.
Mã mã gây ra vấn đềThat Causes The ProblemNhư bạn có thể thấy, trang HTML có phần tử 2 với 3 được gọi là 4.
Đây là nơi tôi đã thêm năm nút sử dụng vòng lặp 5 trong mã JavaScript bên dưới.
Tôi cũng đã đính kèm một sự kiện nhấp chuột vào một phần tử nút và thêm nó vào phần tử 6 trên mỗi lần lặp.Nếu tôi chạy mã ở giai đoạn này, tôi sẽ nhận được giá trị 5 bất kể nhấn nút nào. Trước khi hiểu những gì xảy ra ở đây, chúng tôi cần biết những gì đang nâng cao.
KéoTheo mặc định, một biến được khai báo với từ khóa 7 là chức năng phạm vi nhưng không có khối.function scoped but not block-scoped.Vì vậy, bất kỳ biến nào được khai báo bên trong một hàm, bất kể nó sâu đến mức nào, sẽ được di chuyển lên đỉnh và có thể truy cập ở bất cứ đâu bên trong chức năng đó. Mặt khác, nếu một biến được khai báo bên ngoài hàm, nó sẽ trở thành một biến phạm vi toàn cầu và chúng ta có thể truy cập nó ở bất cứ đâu trong ứng dụng vì nó thuộc về đối tượng cửa sổ (chỉ trình duyệt). Hành vi đó được gọi là nâng.Hoisting. Biến var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
|
Hãy để xem những gì xảy ra với mã ở trên bây giờ.
Biến
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
8 được khai báo với từ khóa var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
7 sẽ được tự động di chuyển lên đầu trang vì nó không được khai báo bên trong một hàm để nó trở thành biến toàn cầu do nâng.Vì vậy, biến
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
8 rõ ràng không được đưa vào vòng lặp var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
5, nhưng nó có phạm vi toàn cầu và nó ràng buộc với cùng một biến bên ngoài hàm gọi lại trên mỗi lần lặp.Vào thời điểm vòng lặp
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
5 đạt đến lần lặp cuối cùng, biến var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
8 sẽ kết thúc giữ giá trị chỉ mục cuối cùng. Đó là lý do tại sao đầu ra sẽ luôn là chỉ số cuối cùng, trong trường hợp của tôi, 5.✅RECOMPENDERJAVASCRIPT làm việc với hình ảnh
JavaScript Working with Images
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
8 là một biến toàn cầu
Tôi sẽ đăng nhập bảng điều khiển Biến tôi bên ngoài vòng lặp.
} // end of for loop
console.log(i);
Bạn sẽ nhận được 5 trong bảng điều khiển trình duyệt ngay khi mã hoàn thành thực thi mà không cần nhấp vào bất kỳ nút nào.
Điều này chứng minh rằng biến
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
8 được phạm vi toàn cầu.Bây giờ chúng tôi biết thủ phạm, đó là biến
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
8 được khai báo với từ khóa var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
7.Hãy cùng xem một vài giải pháp để khắc phục nó.
Giải pháp số 1: Đóng cửa
Chúng ta có thể sử dụng đóng cửa để thay đổi phạm vi của biến
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
8 cho phép các chức năng có thể có các biến riêng tư.Sử dụng đóng, chúng ta có thể lưu duy nhất chỉ mục vòng lặp riêng biệt trên mỗi hàm gọi lại.
for (var i = 0; i < 5; i++) {
var button = document.createElement("button");
button.innerText = i;
(function(index){
button.addEventListener("click", function() {
console.log(index)
})
})(i)
buttonsContainer.appendChild(button);
}
console.log(i);
Hãy cùng xem điều đó trong hành động.
Đầu tiên, xác định đóng cửa bằng cách sử dụng dấu ngoặc đơn mở và đóng bên trong vòng
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
5.Sau đó, khai báo một hàm ẩn danh lấy tham số chỉ mục.
Sau đó, chuyển biến toàn cầu
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
8 vào việc đóng cửa với bộ cuối cùng của (), gọi việc đóng cửa một lần trên mỗi lần lặp.Điều này cũng được gọi là biểu thức chức năng được gọi ngay lập tức (iife), đây là một cách để khai báo đóng cửa.Immediately Invoked Function Expression (IIFE) which is one way of declaring closures.
(function(){
})()
Vì vậy, mã trên nắm bắt giá trị của biến
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
8 tại mỗi lần lặp và chuyển nó thành một đối số cho hàm tạo ra một phạm vi cục bộ.Bây giờ, mỗi hàm có phiên bản riêng của một biến chỉ mục đã giành được sự thay đổi khi các hàm được tạo trong vòng lặp đó.
Hàm đóng cửa này bảo tồn giá trị của
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
8 (biến riêng tư) duy nhất cho mỗi trình xử lý sự kiện để mỗi người có quyền truy cập vào giá trị riêng của chúng.Khi bạn nhấp vào bất kỳ nút nào sau khi kết thúc vòng lặp, chức năng gọi lại thích hợp sẽ được thực thi với giá trị chỉ mục chính xác.
Tôi hy vọng điều đó đúng.
Những điều cơ bản về JavaScript được đề xuất cho người mới bắt đầu
JavaScript Basics for Beginners
Giải pháp #2: Đóng hàm bên ngoài đóng lại chức năng bên trong
Ngoài ra, bạn có thể trả về một hàm bên trong chức năng gọi lại đóng.
button.addEventListener("click", function(index) {
return function(){
console.log(index)
}
}(i))
Trong ví dụ trước, toàn bộ nút Nhấp vào Mã người nghe sự kiện được gói với đóng cửa.
Trong ví dụ này, chỉ cần nút Nhấp vào chức năng gọi lại được kết thúc bằng một đóng cửa.
Hàm bên ngoài sẽ được thực thi trên mọi lần lặp và
const buttonsContainer = document.getElementById("buttonsContainer");
for (var i = 0; i < 5; i++) {
const button = document.createElement("button");
button.innerText = i;
button.addEventListener("click", function() {
console.log(i)
})
buttonsContainer.appendChild(button);
}
5Varable (toàn cầu) được truyền như một đối số trong người gọi của hàm bên ngoài như thế này (i).Hàm bên trong sẽ được trả về trên mỗi lần lặp và được gắn vào sự kiện nhấp chuột với giá trị chỉ mục duy nhất.
Đóng cửa, các hàm bên trong có thể có quyền truy cập vào các biến được khai báo bên ngoài nó ngay cả sau khi hàm bên ngoài được trả về.
Giải pháp #3: Sử dụng const buttonsContainer = document.getElementById("buttonsContainer");
for (var i = 0; i < 5; i++) {
const button = document.createElement("button");
button.innerText = i;
button.addEventListener("click", function() {
console.log(i)
})
buttonsContainer.appendChild(button);
}
6 thay vì var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
5
Điều này sẽ rất tuyệt nếu bạn có một loạt các mục và bạn có thể chỉ cần chạy phương thức
const buttonsContainer = document.getElementById("buttonsContainer");
for (var i = 0; i < 5; i++) {
const button = document.createElement("button");
button.innerText = i;
button.addEventListener("click", function() {
console.log(i)
})
buttonsContainer.appendChild(button);
}
8 trên đó, nhưng nó không được khuyến nghị khi một hoạt động không đồng bộ đang xảy ra trên mọi lần lặp.Theo mặc định, vòng lặp
const buttonsContainer = document.getElementById("buttonsContainer");
for (var i = 0; i < 5; i++) {
const button = document.createElement("button");
button.innerText = i;
button.addEventListener("click", function() {
console.log(i)
})
buttonsContainer.appendChild(button);
}
6 cung cấp một cách sạch sẽ và tự nhiên để có được chức năng đóng gọi lại riêng biệt trên mỗi lần lặp.const num = [0, 1, 2, 3, 4];
num.forEach(i => {
var button = document.createElement("button");
button.innerText = i;
button.addEventListener("click", function() {
console.log(i)
})
buttonsContainer.appendChild(button);
})
Nó hoạt động mà không cần thêm bất kỳ chức năng trình bao bọc bổ sung nào, sạch hơn so với ví dụ trước!
✅RECOMPENDSCORS Lỗi & Giải pháp trong một Nutshell
CORS Error & Solutions in a Nutshell
Giải pháp số 4: Sử dụng } // end of for loop
console.log(i);0 thay vì var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
7} // end of for loop
console.log(i);0 Instead Of var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
7
Trong ES6, chúng tôi có các từ khóa
} // end of for loop
console.log(i);
0 và } // end of for loop
console.log(i);
3 được phân tách khối trái ngược với var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
7 là chức năng phạm vi. Nói cách khác, } // end of for loop
console.log(i);
0 và } // end of for loop
console.log(i);
3 cũng được nâng lên như VAR nhưng chúng không được khởi tạo với giá trị mặc định.block-scoped in contrast to var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
7 that is function scoped. In other words, } // end of for loop
console.log(i);
0 and } // end of for loop
console.log(i);
3 are also hoisted like
var but they’re not initialized with a default value.Vì vậy, sử dụng từ khóa
} // end of for loop
console.log(i);
0 liên kết một hàm gọi lại mới với giá trị chỉ mục trên mỗi lần lặp thay vì sử dụng cùng một tham chiếu nhiều lần.Để khắc phục điều đó, thay đổi
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
7 thành } // end of for loop
console.log(i);
0 từ mã gốc và nó hoạt động.for (let i = 0; i < 5; i++) {
const button = document.createElement("button");
button.innerText = i;
button.addEventListener("click", function() {
console.log(i)
})
buttonsContainer.appendChild(button);
}
Đây là cách nhanh nhất để khắc phục sự kiện nhấp chuột trong một vòng lặp.
Nhưng, một vấn đề với phương pháp này là cẩn thận với khả năng tương thích ngược của trình duyệt vì nó là một phần của tính năng ES6.
✅recomendendsjavascript: Hiểu các phần kỳ lạ
JavaScript: Understanding the Weird Parts
Khai báo chức năng gọi lại bên ngoài vòng lặp
Đôi khi chúng tôi muốn khai báo một chức năng gọi lại một cách riêng biệt với một tên thay vì sử dụng hàm ẩn danh nội tuyến bên trong hàm tạo addEventListener.
Vì vậy, hãy khai báo một hàm gọi lại được gọi là hàm nút được () và gọi nó bên trong hàm tạo addEventListener mà không có dấu ngoặc đơn.
Theo mặc định, đối tượng
for (var i = 0; i < 5; i++) {
var button = document.createElement("button");
button.innerText = i;
(function(index){
button.addEventListener("click", function() {
console.log(index)
})
})(i)
buttonsContainer.appendChild(button);
}
console.log(i);
0 được chuyển vào hàm nút ().Sau đó, tôi có thể dễ dàng truy cập vào bất kỳ thông tin nào về phần tử đã chọn bằng đối tượng
for (var i = 0; i < 5; i++) {
var button = document.createElement("button");
button.innerText = i;
(function(index){
button.addEventListener("click", function() {
console.log(index)
})
})(i)
buttonsContainer.appendChild(button);
}
console.log(i);
0.var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
0Điều gì sẽ xảy ra nếu tôi muốn chuyển một giá trị trực tiếp đến hàm gọi lại như một đối số?
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
1Điều này rất giống với giải pháp #2.
Khi chúng ta chuyển một giá trị cho
for (var i = 0; i < 5; i++) {
var button = document.createElement("button");
button.innerText = i;
(function(index){
button.addEventListener("click", function() {
console.log(index)
})
})(i)
buttonsContainer.appendChild(button);
}
console.log(i);
2, nó trở thành một đóng cửa (iife) là hàm bên ngoài và chạy trên mỗi lần lặp.Hàm bên trong sẽ được trả về trên mỗi lần lặp và gắn vào sự kiện nhấp chuột với giá trị chỉ mục.
Và điều đó sẽ làm phép thuật!
Hướng dẫn MVC JavaScript được đề xuất bằng ES6 - Phần 01
MVC JavaScript Tutorial Using ES6 – Part 01
Sự kết luận
Trong bài viết này, bạn đã học cách khắc phục sự cố phát sinh khi bạn đính kèm các sự kiện nhấp vào vòng lặp
var buttons = document.querySelectorAll("td>button");
for(var button = 0; button < buttons.length; button++)
{
button.addEventListener("click", function() {
document.getElementById("user-input").value += button.value;
document.getElementById("user-input").focus();
});
}
});
Test
5 theo một vài cách.Phạm vi trong JavaScript là một chủ đề lớn và tôi vẫn đang tìm hiểu về việc đóng cửa và các khái niệm khác trong JavaScript.
Nếu bạn có bất kỳ đề xuất, phản hồi hoặc nếu có bất cứ điều gì không rõ ràng trong bài viết này, xin vui lòng liên hệ với tôi bằng cách bình luận bên dưới.
Tôi rất mong nhận được phản hồi từ bạn và mã hóa hạnh phúc!