Đoàn sự kiện DOM là gì?


202

Bất cứ ai cũng có thể giải thích về sự kiện ủy quyền trong JavaScript và nó hữu ích như thế nào?


2
Thật tuyệt nếu có một liên kết đến nguồn thông tin hữu ích về việc này. 6 giờ sau, đây là lượt truy cập hàng đầu của google cho "phái đoàn sự kiện dom". Có lẽ đây là một liên kết hữu ích? Tôi không hoàn toàn chắc chắn: w3.org/TR/DOM-Level-2-Events/events.html
Sean McMillan

Hoặc có thể thế này: sitepoint.com/bloss/2008/07/23/ từ
Sean McMillan

7
Đây là một phổ biến. Ngay cả các chàng trai fb cũng liên kết đến trang này cho trang Reacjs của họ davidwalsh.name/event-delegate
Sorter

Xem javascript.info/event-delegation này nó sẽ giúp bạn rất nhiều
Suraj Jain

Câu trả lời:


330

Sự kiện DOM là một cơ chế phản ứng với các sự kiện thông qua một phụ huynh chung chứ không phải mỗi đứa trẻ, thông qua phép thuật của sự kiện "sủi bọt" (hay còn gọi là truyền bá sự kiện).

Khi một sự kiện được kích hoạt trên một phần tử, điều sau đây xảy ra :

Sự kiện này được gửi đến mục tiêu của nó EventTargetvà bất kỳ người nghe sự kiện nào được tìm thấy ở đó đều được kích hoạt. Sau đó, các sự kiện bong bóng sẽ kích hoạt bất kỳ trình lắng nghe sự kiện bổ sung nào được tìm thấy bằng cách theo dõi EventTargetchuỗi cha mẹ trở lên , kiểm tra xem có bất kỳ trình lắng nghe sự kiện nào đã đăng ký trên mỗi EventTarget liên tiếp không. Sự truyền bá đi lên này sẽ tiếp tục lên đến và bao gồm cả Document.

Sự kiện sủi bọt cung cấp nền tảng cho sự kiện ủy nhiệm trong các trình duyệt. Bây giờ bạn có thể liên kết một trình xử lý sự kiện với một phần tử cha đơn lẻ và trình xử lý đó sẽ được thực thi bất cứ khi nào sự kiện xảy ra trên bất kỳ nút con nào của nó (và bất kỳ con nào của chúng lần lượt). Đây là đoàn sự kiện. Đây là một ví dụ về nó trong thực tế:

<ul onclick="alert(event.type + '!')">
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
</ul>

Với ví dụ đó nếu bạn nhấp vào bất kỳ <li>nút con nào , bạn sẽ thấy một cảnh báo "click!", mặc dù không có trình xử lý nhấp chuột nào bị ràng buộc với nút <li>bạn đã nhấp vào. Nếu chúng tôi ràng buộc onclick="..."với từng <li>bạn sẽ có được hiệu ứng tương tự.

Vậy lợi ích là gì?

Hãy tưởng tượng bây giờ bạn có nhu cầu tự động thêm các <li>mục mới vào danh sách trên thông qua thao tác DOM:

var newLi = document.createElement('li');
newLi.innerHTML = 'Four';
myUL.appendChild(newLi);

Nếu không sử dụng ủy quyền sự kiện, bạn sẽ phải "khởi động lại" "onclick"trình xử lý sự kiện sang <li>phần tử mới , để nó hoạt động giống như anh chị em của nó. Với đoàn sự kiện, bạn không cần phải làm gì cả. Chỉ cần thêm cái mới <li>vào danh sách và bạn đã hoàn thành.

Điều này hoàn toàn tuyệt vời cho các ứng dụng web với trình xử lý sự kiện được liên kết với nhiều yếu tố, trong đó các yếu tố mới được tạo động và / hoặc loại bỏ trong DOM. Với ủy nhiệm sự kiện, số lượng ràng buộc sự kiện có thể giảm đáng kể bằng cách di chuyển chúng đến một phần tử cha chung và mã tạo ra các phần tử mới một cách linh hoạt có thể được tách rời khỏi logic ràng buộc các trình xử lý sự kiện của chúng.

Một lợi ích khác cho việc ủy ​​quyền sự kiện là tổng dung lượng bộ nhớ được sử dụng bởi người nghe sự kiện đi xuống (vì số lượng ràng buộc sự kiện giảm xuống). Nó có thể không tạo ra nhiều sự khác biệt đối với các trang nhỏ không tải thường xuyên (tức là người dùng thường xuyên điều hướng đến các trang khác nhau). Nhưng đối với các ứng dụng lâu dài, nó có thể là đáng kể. Có một số tình huống thực sự khó theo dõi khi các phần tử bị xóa khỏi DOM vẫn yêu cầu bộ nhớ (tức là chúng bị rò rỉ) và thường bộ nhớ bị rò rỉ này được gắn với một ràng buộc sự kiện. Với phái đoàn sự kiện, bạn có thể tự do phá hủy các yếu tố con mà không có nguy cơ quên "hủy kết nối" người nghe sự kiện của họ (vì người nghe ở trên tổ tiên). Những loại rò rỉ bộ nhớ sau đó có thể được chứa (nếu không được loại bỏ, điều này đôi khi rất khó thực hiện. IE tôi đang nhìn bạn).

Dưới đây là một số ví dụ mã cụ thể tốt hơn của phái đoàn sự kiện:


Tôi đã bị cấm truy cập khi mở liên kết thứ ba của bạn Đoàn không có thư viện javascript và +1 cho liên kết cuối cùng của bạn
bugwheels94

Xin chào, cảm ơn bạn đã giải thích tuyệt vời. Tôi vẫn còn bối rối về một chi tiết nhất định: Cách tôi hiểu luồng sự kiện của cây DOM (Như có thể thấy trong 3.1. Luồng sự kiện và luồng sự kiện DOM ) đối tượng sự kiện lan truyền cho đến khi đến phần tử đích rồi nổi lên. Tại sao nó có thể tiếp cận các phần tử con của một nút nếu cha mẹ của nút này là mục tiêu sự kiện được đề cập? ví dụ: làm thế nào để sự kiện có thể lan truyền đến <li>khi nào nó nên dừng lại <ul>? Nếu câu hỏi của tôi vẫn chưa rõ ràng hoặc cần một chủ đề riêng biệt, tôi rất vui lòng bắt buộc.
Aetos

@Aetos: > Làm thế nào mà nó có thể tiếp cận các phần tử con của một nút nếu cha mẹ của nút này là mục tiêu sự kiện trong câu hỏi? Nó không thể, như tôi hiểu nó. Sự kiện kết thúc giai đoạn 1 (bắt giữ) tại cha mẹ của mục tiêu, đi vào giai đoạn 2 (mục tiêu) trên chính mục tiêu, sau đó bước vào giai đoạn 3 (sủi bọt) bắt đầu từ cha mẹ của mục tiêu. Không nơi nào nó đạt đến một đứa trẻ của mục tiêu.
Lưỡi liềm tươi

@Crescent Tươi tốt thì sự kiện sẽ áp dụng như thế nào trên nút con nếu nó không bao giờ đến được?
Aetos

1
Câu trả lời thực sự tuyệt vời. Cảm ơn đã giải thích đoàn sự kiện với sự thật có liên quan. Cảm ơn!
Kshitij Tiwari

30

Phân quyền sự kiện cho phép bạn tránh thêm trình lắng nghe sự kiện vào các nút cụ thể; thay vào đó, trình lắng nghe sự kiện được thêm vào một phụ huynh. Người nghe sự kiện đó phân tích các sự kiện sủi bọt để tìm ra sự trùng khớp về các yếu tố con.

Ví dụ về JavaScript:

Hãy nói rằng chúng ta có một phần tử UL cha mẹ với một số phần tử con:

<ul id="parent-list">
<li id="post-1">Item 1</li>
<li id="post-2">Item 2</li>
<li id="post-3">Item 3</li>
<li id="post-4">Item 4</li>
<li id="post-5">Item 5</li>
<li id="post-6">Item 6</li>

Chúng ta cũng nói rằng một cái gì đó cần phải xảy ra khi mỗi phần tử con được nhấp. Bạn có thể thêm một trình lắng nghe sự kiện riêng cho từng phần tử LI riêng lẻ, nhưng nếu các phần tử LI thường xuyên được thêm và xóa khỏi danh sách thì sao? Thêm và xóa người nghe sự kiện sẽ là một cơn ác mộng, đặc biệt là nếu mã bổ sung và loại bỏ ở những nơi khác nhau trong ứng dụng của bạn. Giải pháp tốt hơn là thêm một trình lắng nghe sự kiện vào phần tử UL gốc. Nhưng nếu bạn thêm trình lắng nghe sự kiện cho phụ huynh, làm thế nào bạn biết được phần tử nào được nhấp?

Đơn giản: khi sự kiện nổi lên đến phần tử UL, bạn kiểm tra thuộc tính đích của đối tượng sự kiện để có được tham chiếu đến nút được nhấp thực tế. Đây là một đoạn mã JavaScript rất cơ bản minh họa cho sự kiện ủy nhiệm:

// Get the element, add a click listener...
document.getElementById("parent-list").addEventListener("click", function(e) {
// e.target is the clicked element!
// If it was a list item
if(e.target && e.target.nodeName == "LI") {
    // List item found!  Output the ID!
    console.log("List item ", e.target.id.replace("post-"), " was clicked!");
       }
 });

Bắt đầu bằng cách thêm một trình lắng nghe sự kiện nhấp vào phần tử cha. Khi trình lắng nghe sự kiện được kích hoạt, hãy kiểm tra phần tử sự kiện để đảm bảo đó là loại phần tử sẽ phản ứng. Nếu đó là một yếu tố LI, hãy bùng nổ: chúng ta có những gì chúng ta cần! Nếu đó không phải là một yếu tố mà chúng tôi muốn, sự kiện có thể bị bỏ qua. Ví dụ này khá đơn giản - UL và LI là một so sánh đơn giản. Hãy thử một cái gì đó khó khăn hơn. Chúng ta có một cha mẹ DIV có nhiều con nhưng tất cả những gì chúng ta quan tâm là một thẻ A với lớp CSS classA:

  // Get the parent DIV, add click listener...
  document.getElementById("myDiv").addEventListener("click",function(e) {
// e.target was the clicked element
if(e.target && e.target.nodeName == "A") {
    // Get the CSS classes
    var classes = e.target.className.split(" ");
    // Search for the CSS class!
    if(classes) {
        // For every CSS class the element has...
        for(var x = 0; x < classes.length; x++) {
            // If it has the CSS class we want...
            if(classes[x] == "classA") {
                // Bingo!
                console.log("Anchor element clicked!");
                // Now do something here....
            }
        }
    }

  }
});

http://davidwalsh.name/event-delegate


1
Tinh chỉnh được đề xuất: sử dụng e. ClassList.contains () trong ví dụ cuối cùng: developer.mozilla.org/en-US/docs/Web/API/Euity/
nc.

7

phái đoàn sự kiện dom là một cái gì đó khác với định nghĩa khoa học máy tính.

Nó đề cập đến việc xử lý các sự kiện sủi bọt từ nhiều thành phần, như các ô của bảng, từ một đối tượng cha, như bảng. Nó có thể giữ mã đơn giản hơn, đặc biệt là khi thêm hoặc xóa các phần tử và tiết kiệm một số bộ nhớ.


6

Phân quyền là một kỹ thuật trong đó một đối tượng thể hiện một số hành vi nhất định ra bên ngoài nhưng trong thực tế, đại biểu chịu trách nhiệm thực hiện hành vi đó cho một đối tượng liên quan. Điều này thoạt nghe rất giống với mẫu proxy, nhưng nó phục vụ một mục đích khác. Phân quyền là một cơ chế trừu tượng hóa tập trung vào hành vi của đối tượng (phương thức).

Nói chung: sử dụng ủy quyền thay thế cho thừa kế. Kế thừa là một chiến lược tốt, khi một mối quan hệ chặt chẽ tồn tại ở giữa đối tượng cha mẹ và con cái, tuy nhiên, thừa kế cặp vợ chồng đối tượng rất chặt chẽ. Thông thường, ủy quyền là cách linh hoạt hơn để thể hiện mối quan hệ giữa các lớp.

Mẫu này còn được gọi là "chuỗi proxy". Một số mẫu thiết kế khác sử dụng ủy quyền - Nhà nước, Chiến lược và Mẫu khách truy cập phụ thuộc vào nó.


Lời giải thích hay. Trong ví dụ về <ul> với một số <li> con, rõ ràng <li> là những người xử lý logic nhấp chuột, nhưng không phải như vậy bởi vì họ "ủy thác" logic này ở người cha <ul>
Juanma Menendez

6

Khái niệm đoàn

Nếu có nhiều phần tử bên trong một cha mẹ và bạn muốn xử lý các sự kiện trên chúng - đừng ràng buộc các trình xử lý với từng phần tử. Thay vào đó, ràng buộc trình xử lý duy nhất với cha mẹ của chúng và đưa đứa trẻ từ event.target. Trang web này cung cấp thông tin hữu ích về cách triển khai ủy quyền sự kiện. http://javascript.info/tutorial/event-delegation


6

Đoàn sự kiện đang xử lý một sự kiện bong bóng bằng cách sử dụng trình xử lý sự kiện trên phần tử container, nhưng chỉ kích hoạt hành vi của trình xử lý sự kiện nếu sự kiện xảy ra trên một phần tử trong vùng chứa khớp với điều kiện đã cho. Điều này có thể đơn giản hóa việc xử lý các sự kiện trên các phần tử trong vùng chứa.

Chẳng hạn, giả sử bạn muốn xử lý một nhấp chuột vào bất kỳ ô bảng nào trong một bảng lớn. Bạn có thể viết một vòng lặp để nối trình xử lý nhấp chuột vào từng ô ... hoặc bạn có thể kết nối trình xử lý nhấp chuột trên bảng và sử dụng ủy nhiệm sự kiện để kích hoạt nó chỉ cho các ô của bảng (chứ không phải tiêu đề bảng hoặc khoảng trắng trong một hàng xung quanh các tế bào, vv).

Nó cũng hữu ích khi bạn sẽ thêm và xóa các phần tử khỏi vùng chứa, bởi vì bạn không phải lo lắng về việc thêm và xóa trình xử lý sự kiện trên các phần tử đó; chỉ cần móc sự kiện trên container và xử lý sự kiện khi nó sủi bọt.

Đây là một ví dụ đơn giản (nó cố ý dài dòng để cho phép giải thích nội tuyến): Xử lý một nhấp chuột vào bất kỳ tdphần tử nào trong bảng chứa:

// Handle the event on the container
document.getElementById("container").addEventListener("click", function(event) {
    // Find out if the event targeted or bubbled through a `td` en route to this container element
    var element = event.target;
    var target;
    while (element && !target) {
        if (element.matches("td")) {
            // Found a `td` within the container!
            target = element;
        } else {
            // Not found
            if (element === this) {
                // We've reached the container, stop
                element = null;
            } else {
                // Go to the next parent in the ancestry
                element = element.parentNode;
            }
        }
    }
    if (target) {
        console.log("You clicked a td: " + target.textContent);
    } else {
        console.log("That wasn't a td in the container table");
    }
});
table {
    border-collapse: collapse;
    border: 1px solid #ddd;
}
th, td {
    padding: 4px;
    border: 1px solid #ddd;
    font-weight: normal;
}
th.rowheader {
    text-align: left;
}
td {
    cursor: pointer;
}
<table id="container">
    <thead>
        <tr>
            <th>Language</th>
            <th>1</th>
            <th>2</th>
            <th>3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th class="rowheader">English</th>
            <td>one</td>
            <td>two</td>
            <td>three</td>
        </tr>
        <tr>
            <th class="rowheader">Español</th>
            <td>uno</td>
            <td>dos</td>
            <td>tres</td>
        </tr>
        <tr>
            <th class="rowheader">Italiano</th>
            <td>uno</td>
            <td>due</td>
            <td>tre</td>
        </tr>
    </tbody>
</table>

Trước khi đi vào chi tiết về điều đó, chúng ta hãy tự nhắc nhở mình cách các sự kiện DOM hoạt động.

Các sự kiện DOM được gửi từ tài liệu đến phần tử đích ( giai đoạn bắt giữ ) và sau đó bong bóng từ phần tử đích trở lại tài liệu ( pha sủi bọt ). Đồ họa này trong thông số sự kiện DOM3 cũ (hiện đã được áp dụng, nhưng đồ họa vẫn còn hiệu lực) cho thấy nó thực sự tốt:

nhập mô tả hình ảnh ở đây

Không phải tất cả các sự kiện bong bóng, nhưng hầu hết làm, bao gồm click.

Các ý kiến ​​trong ví dụ mã ở trên mô tả cách thức hoạt động. matcheskiểm tra xem một phần tử có khớp với bộ chọn CSS hay không, nhưng tất nhiên bạn có thể kiểm tra xem có thứ gì phù hợp với tiêu chí của bạn theo những cách khác hay không nếu bạn không muốn sử dụng bộ chọn CSS.

Mã đó được viết để gọi ra từng bước riêng lẻ, nhưng trên các trình duyệt hiện đại mơ hồ (và cả trên IE nếu bạn sử dụng polyfill), bạn có thể sử dụng closestcontainsthay vì vòng lặp:

var target = event.target.closest("td");
    console.log("You clicked a td: " + target.textContent);
} else {
    console.log("That wasn't a td in the container table");
}

Ví dụ trực tiếp:

closestkiểm tra phần tử mà bạn gọi nó để xem nó có khớp với bộ chọn CSS đã cho không và nếu có, nó sẽ trả về phần tử đó; nếu không, nó sẽ kiểm tra phần tử cha để xem nó có khớp hay không và trả về phần tử cha nếu có; nếu không, nó sẽ kiểm tra cha mẹ của cha mẹ, v.v. Vì vậy, nó tìm thấy phần tử "gần nhất" trong danh sách tổ tiên phù hợp với bộ chọn. Vì điều đó có thể đi qua phần tử container, đoạn mã trên sử dụngcontains để kiểm tra xem có tìm thấy phần tử phù hợp không, nó nằm trong vùng chứa - vì bằng cách móc sự kiện trên vùng chứa, bạn đã cho biết bạn chỉ muốn xử lý các phần tử trong vùng chứa đó .

Quay trở lại ví dụ về bảng của chúng tôi, điều đó có nghĩa là nếu bạn có một bảng trong một ô của bảng, nó sẽ không khớp với ô bảng chứa bảng:


3

Về cơ bản, đó là cách liên kết được thực hiện với các yếu tố. .clickáp dụng cho DOM hiện tại, trong khi .on(sử dụng ủy quyền) sẽ tiếp tục hợp lệ cho các thành phần mới được thêm vào DOM sau khi liên kết sự kiện.

Cái nào tốt hơn để sử dụng, tôi muốn nói nó phụ thuộc vào trường hợp.

Thí dụ:

<ul id="todo">
   <li>Do 1</li>
   <li>Do 2</li>
   <li>Do 3</li>
   <li>Do 4</li>
</ul>

.Nhấp sự kiện:

$("li").click(function () {
   $(this).remove ();
});

Sự kiện .on:

$("#todo").on("click", "li", function () {
   $(this).remove();
});

Lưu ý rằng tôi đã tách bộ chọn trong .on. Tôi sẽ giải thích tại sao.

Chúng ta hãy giả sử rằng sau hiệp hội này, chúng ta hãy làm như sau:

$("#todo").append("<li>Do 5</li>");

Đó là nơi bạn sẽ nhận thấy sự khác biệt.

Nếu sự kiện được liên kết thông qua .click, tác vụ 5 sẽ không tuân theo sự kiện nhấp chuột và vì vậy nó sẽ không bị xóa.

Nếu nó được liên kết thông qua .on, với bộ chọn riêng biệt, nó sẽ tuân theo.


2

Để hiểu về ủy nhiệm sự kiện trước tiên chúng ta cần biết tại sao và khi nào chúng ta thực sự cần hoặc muốn ủy thác sự kiện.

Có thể có nhiều trường hợp nhưng chúng ta hãy thảo luận về hai trường hợp sử dụng lớn cho phái đoàn sự kiện. 1. Trường hợp đầu tiên là khi chúng ta có một phần tử có nhiều phần tử con mà chúng ta quan tâm. Trong trường hợp này, thay vì thêm một trình xử lý sự kiện cho tất cả các phần tử con này, chúng ta chỉ cần thêm nó vào phần tử cha và sau đó xác định trên đó yếu tố con sự kiện đã bị sa thải.

2. Trường hợp sử dụng thứ hai cho ủy nhiệm sự kiện là khi chúng tôi muốn một trình xử lý sự kiện được đính kèm với một phần tử chưa có trong DOM khi trang của chúng tôi được tải. Tất nhiên, đó là bởi vì chúng tôi không thể thêm một trình xử lý sự kiện vào một thứ không có trên trang của chúng tôi, vì vậy trong trường hợp không được chấp nhận rằng chúng tôi đang mã hóa.

Giả sử bạn có một danh sách 0, 10 hoặc 100 mục trong DOM khi bạn tải trang của mình và nhiều mục khác đang chờ trong tay bạn để thêm vào danh sách. Vì vậy, không có cách nào để đính kèm một trình xử lý sự kiện cho các phần tử trong tương lai hoặc các phần tử đó chưa được thêm vào DOM và cũng có thể có rất nhiều mục, vì vậy sẽ không hữu ích khi có một trình xử lý sự kiện được gắn vào mỗi phần tử của họ.

Đoàn sự kiện

Được rồi, vì vậy để nói về phái đoàn sự kiện, khái niệm đầu tiên mà chúng ta thực sự cần nói đến là sự kiện sôi nổi.

Bong bóng sự kiện: Bong bóng sự kiện có nghĩa là khi một sự kiện được kích hoạt hoặc kích hoạt trên một số phần tử DOM, ví dụ bằng cách nhấp vào nút của chúng tôi ở đây trên hình ảnh dưới đây, thì sự kiện tương tự cũng được kích hoạt trên tất cả các thành phần chính.

nhập mô tả hình ảnh ở đây

Sự kiện này lần đầu tiên được kích hoạt trên nút, nhưng sau đó nó cũng sẽ được bắn vào tất cả các phần tử cha một lần, do đó, nó cũng sẽ bắn vào đoạn tới phần chính và thực sự đi lên trong cây DOM cho đến khi phần tử HTML là gốc. Vì vậy, chúng tôi nói rằng sự kiện này nổi lên bên trong cây DOM và đó là lý do tại sao nó được gọi là bong bóng.

1 2 3 4

Phần tử mục tiêu: Phần tử mà sự kiện được thực hiện lần đầu tiên được gọi là phần tử đích, do đó phần tử gây ra sự kiện xảy ra, được gọi là phần tử đích. Trong ví dụ trên của chúng tôi ở đây, dĩ nhiên, nút được nhấp. Phần quan trọng là phần tử đích này được lưu trữ như một thuộc tính trong đối tượng sự kiện, Điều này có nghĩa là tất cả các phần tử cha mà sự kiện cũng sẽ bắn sẽ biết phần tử đích của sự kiện, do đó sự kiện được bắn lần đầu tiên.

Điều đó đưa chúng ta đến với sự kiện bởi vì nếu sự kiện nổi lên trong cây DOM và nếu chúng ta biết sự kiện được bắn ở đâu thì chúng ta chỉ cần gắn một trình xử lý sự kiện vào một phần tử cha và chờ sự kiện nổi lên và chúng ta có thể sau đó làm bất cứ điều gì chúng tôi dự định làm với yếu tố mục tiêu của chúng tôi. Kỹ thuật này được gọi là đoàn sự kiện. Trong ví dụ này ở đây, chúng ta chỉ cần thêm trình xử lý sự kiện vào thành phần chính.

Được rồi, vì vậy, một lần nữa, phái đoàn sự kiện là không thiết lập trình xử lý sự kiện trên phần tử ban đầu mà chúng ta quan tâm mà gắn nó vào phần tử cha và, về cơ bản, bắt sự kiện ở đó vì nó nổi lên. Sau đó chúng ta có thể hành động dựa trên yếu tố mà chúng ta quan tâm khi sử dụng thuộc tính phần tử đích.

Ví dụ: Bây giờ giả sử chúng tôi có hai mục danh sách trong trang của mình, sau khi thêm các mục trong danh sách đó theo chương trình, chúng tôi muốn xóa một hoặc nhiều mục khỏi chúng. Sử dụng tecnique ủy nhiệm sự kiện, chúng ta có thể đạt được mục đích của mình một cách dễ dàng.

<div class="body">
    <div class="top">

    </div>
    <div class="bottom">
        <div class="other">
            <!-- other bottom elements -->
        </div>
        <div class="container clearfix">
            <div class="income">
                <h2 class="icome__title">Income</h2>
                <div class="income__list">
                    <!-- list items -->
                </div>
            </div>
            <div class="expenses">
                <h2 class="expenses__title">Expenses</h2>
                <div class="expenses__list">
                    <!-- list items -->
                </div>
            </div>
        </div>
    </div>
</div>

Thêm các mục trong danh sách đó:

const DOMstrings={
        type:{
            income:'inc',
            expense:'exp'
        },
        incomeContainer:'.income__list',
        expenseContainer:'.expenses__list',
        container:'.container'
   }


var addListItem = function(obj, type){
        //create html string with the place holder
        var html, element;
        if(type===DOMstrings.type.income){
            element = DOMstrings.incomeContainer
            html = `<div class="item clearfix" id="inc-${obj.id}">
            <div class="item__description">${obj.descripiton}</div>
            <div class="right clearfix">
                <div class="item__value">${obj.value}</div>
                <div class="item__delete">
                    <button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button>
                </div>
            </div>
        </div>`
        }else if (type ===DOMstrings.type.expense){
            element=DOMstrings.expenseContainer;
            html = ` <div class="item clearfix" id="exp-${obj.id}">
            <div class="item__description">${obj.descripiton}</div>
            <div class="right clearfix">
                <div class="item__value">${obj.value}</div>
                <div class="item__percentage">21%</div>
                <div class="item__delete">
                    <button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button>
                </div>
            </div>
        </div>`
        }
        var htmlObject = document.createElement('div');
        htmlObject.innerHTML=html;
        document.querySelector(element).insertAdjacentElement('beforeend', htmlObject);
    }

Xóa mục:

var ctrlDeleteItem = function(event){
       // var itemId = event.target.parentNode.parentNode.parentNode.parentNode.id;
        var parent = event.target.parentNode;
        var splitId, type, ID;
        while(parent.id===""){
            parent = parent.parentNode
        }
        if(parent.id){
            splitId = parent.id.split('-');
            type = splitId[0];
            ID=parseInt(splitId[1]);
        }

        deleteItem(type, ID);
        deleteListItem(parent.id);
 }

 var deleteItem = function(type, id){
        var ids, index;
        ids = data.allItems[type].map(function(current){
            return current.id;
        });
        index = ids.indexOf(id);
        if(index>-1){
            data.allItems[type].splice(index,1);
        }
    }

  var deleteListItem = function(selectorID){
        var element = document.getElementById(selectorID);
        element.parentNode.removeChild(element);
    }

1

Một đại biểu trong C # tương tự như một con trỏ hàm trong C hoặc C ++. Sử dụng một ủy nhiệm cho phép lập trình viên đóng gói một tham chiếu đến một phương thức bên trong một đối tượng ủy nhiệm. Đối tượng ủy nhiệm sau đó có thể được chuyển đến mã có thể gọi phương thức được tham chiếu mà không cần phải biết tại thời điểm biên dịch phương thức nào sẽ được gọi.

Xem liên kết này -> http://www.akadia.com/service/dotnet_delegates_and_events.html


5
Tôi sẽ không bỏ phiếu này, vì đây có thể là một câu trả lời chính xác cho câu hỏi ban đầu, nhưng câu hỏi hiện tại cụ thể là về sự kiện DOM & Javascript
iandotkelly 6/213

1

Phân quyền sự kiện sử dụng hai tính năng thường bị bỏ qua của các sự kiện JavaScript: bong bóng sự kiện và phần tử đích. Khi một sự kiện được kích hoạt trên một phần tử, ví dụ như nhấp chuột vào nút, cùng một sự kiện cũng được kích hoạt trên tất cả tổ tiên của phần tử đó . Quá trình này được gọi là bong bóng sự kiện; sự kiện nổi lên từ phần tử gốc đến đỉnh của cây DOM.

Hãy tưởng tượng một bảng HTML có 10 cột và 100 hàng trong đó bạn muốn điều gì đó xảy ra khi người dùng nhấp vào một ô của bảng. Ví dụ, tôi đã từng phải làm cho mỗi ô của một bảng có kích thước đó có thể chỉnh sửa khi nhấp vào. Việc thêm các trình xử lý sự kiện vào mỗi 1000 ô sẽ là một vấn đề hiệu năng lớn và có khả năng là một nguồn rò rỉ bộ nhớ bị lỗi trình duyệt. Thay vào đó, bằng cách sử dụng ủy quyền sự kiện, bạn sẽ chỉ thêm một trình xử lý sự kiện vào thành phần bảng, chặn sự kiện nhấp và xác định ô nào được nhấp.


0
Đoàn sự kiện

Đính kèm một trình lắng nghe sự kiện vào một phần tử cha sẽ kích hoạt khi một sự kiện xảy ra trên một phần tử con.

Tuyên truyền sự kiện

Khi một sự kiện di chuyển qua DOM từ phần tử con sang phần tử cha, đó gọi là Tuyên truyền sự kiện , vì sự kiện này lan truyền hoặc di chuyển qua DOM.

Trong ví dụ này, một sự kiện (onclick) từ một nút được chuyển đến đoạn cha.

$(document).ready(function() {

    $(".spoiler span").hide();

    /* add event onclick on parent (.spoiler) and delegate its event to child (button) */
    $(".spoiler").on( "click", "button", function() {
    
        $(".spoiler button").hide();    
    
        $(".spoiler span").show();
    
    } );

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

<p class="spoiler">
    <span>Hello World</span>
    <button>Click Me</button>
</p>

Codepen

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.