簡體   English   中英

jQuery AJAX 調用在點擊處理程序中被多次觸發

[英]jQuery AJAX calls getting fired multiple times within click handler

I'm currently developing a PHP web app, and I'm making use of the datatables jQuery plugin, and jQuery AJAX calls to create a dynamic table that can have elements edited, deleted and added. 這(似乎)工作正常,但是,我觀察到在我的一些點擊處理程序中,AJAX 調用被多次觸發 - 我不太確定為什么。

這是目前的頁面,所以你知道我來自哪里:

顯示表格的屏幕截圖

如您所見,我有關於用戶的基本數據,以及左側的操作。 表中的每一行在 HTML 中如下所示:

<tr>
    <td><?= $userAccount['firstName'] ?></td>
    <td><?= $userAccount['lastName'] ?></td>
    <td><?= $userAccount['email'] ?></td>
    <td><?= $userAccount['jobTitle'] ?></td>
    <td class="text-right enrolr-datatable-actions-min-width">
        <i data-userId="<?= $userAccount['id'] ?>" class="fas fa-user-edit enrolr-standard-icon mr-2 event-user-edit"></i>
        <i data-userId="<?= $userAccount['id'] ?>" class="fas fa-user-times enrolr-danger-icon mr-2 event-user-delete-staff"></i>
    </td>
</tr>

由於(在初始頁面加載/渲染之后)這些表行被動態刪除/添加,因此我決定在文檔級別監聽事件以單擊.event-user-delete-staff class,如下所示:

$(document).on('click', '.event-user-delete-staff', function () {
    // Storing some details for later use by handlers
    const userEmail = $(this).closest('tr').find('td').eq(2).html();
    const $button = $(this);

    // Shows confirm dialog, only performs deletion when "yes" is clicked, which causes the third function parameter to run
    confirmDialog(`Are you sure you want to delete ${userEmail}? This action cannot be undone.`, 'Confirm Deletion', function () {
        const $parentToRemove = $button.closest('tr');

        // Make post to remove user.
        $.ajax({
            type: 'POST',
            url: '../php/account/_deleteUser.php',
            data: {
                id: $button.attr('data-userId')
            },
            dataType: 'json',
            success: function (response) {
                // Handle response.
                if (response.success == true) {
                    displaySuccessToast(response.message);
                    // Fade out row then update datatable.
                    $parentToRemove.fadeOut(500, () => {
                        staffTable.row($parentToRemove).remove().draw();
                    });
                } else {
                    displayErrorToastStandard(response.message);
                }
            },
            error: function () {
                // Show error on failure.
                displayErrorToastStandard('Something went wrong while handling this request');
            }
        });
    });
});

現在,我注意到 AJAX 調用被多次調用的原因是因為我注意到每個刪除事件都會顯示多個 toast 消息( displaySuccessToast方法,所有這些都是克隆一個 toast 模板並顯示它)。 基本上會發生以下情況:

  1. 第一次從表中刪除 - 工作正常,行被刪除並顯示成功消息。
  2. 從表中第二次刪除 - 這是事情開始變得時髦的地方。 從表中刪除了正確的行,但是,顯示了兩個 toasts 並進行了兩個 AJAX 調用。
  3. 從表中刪除第三次 - 趨勢繼續,現在顯示 3 個 toast,並進行了 3 個 AJAX 調用。

添加了一些控制台日志並單步執行代碼后,我可以看出這不是因為$(document).on('click', '.event-user-delete-staff', function ()事件偵聽器正在觸發多個每次刪除它只會觸發一次,因為它應該。

我認為嫌疑人是confirmDialog()方法,正如我通過一些控制台日志觀察到的那樣,它在這里多次觸發。

此方法如下所示:

window.confirmDialog = function (message, title, yesCallback) {
    // Sets some details in the confirm dialog
    $('#confirmMessage').html(message);
    $('#confirmTitle').html(title);

    // Shows the modal
    $('#confirmModal').modal('show');

    // On the "yes" button within the dialog being clicked, hides modal and calls the yesCallback function.
    $('#confirmBtnYes').on('click', function () {
        $('#confirmModal').modal('hide');
        yesCallback();
    });

    // On "no" just hides the modal.
    $('#confirmBtnNo').on('click', function () {
        $('#confirmModal').modal('hide');
    });
}

但是,我懷疑這並不是這種方法的錯。 但是我對 function 這樣的回調如何工作以及在其中使用父級 scope 的變量是否存在某種誤解?

正如我所說; 我不認為這是因為事件偵聽器本身會觸發多次,在第二次刪除(及以后......)時,事件仍然只記錄被調用一次,它在confirmDialog function 回調方法中,它記錄了兩次.

有人可以告訴我我在這里做錯了什么,什么可能導致這種行為?

編輯- 對於后代,以及其他任何偶然發現這一點並想知道我改變了什么的人......

這種情況下的問題是,每次調用confirmDialog方法時,都會向 yes 按鈕添加另一個偵聽器。 這意味着,當單擊該對話框中的“是”按鈕時,它將觸發最近的事件......以及之前附加的所有其他事件。 我只是將確認按鈕是對話框更改為如下所示:

$('#confirmBtnYes').off().on('click', function () {
    $('#confirmModal').modal('hide');
    yesCallback();
});

首先使用off()可確保沒有其他事件偵聽器在該 yes 按鈕上徘徊。 可能不是最好或最干凈的解決方案,但嘿,它有效。

感謝尼克在下面的回答,他指出了我哪里出錯了

每次調用confirmDialog時,您都會在確認對話框中的Yes按鈕中添加一個新的事件處理程序:

$('#confirmBtnYes').on('click', function () {
    $('#confirmModal').modal('hide');
    yesCallback();
});

這意味着第一次單擊 yes 按鈕時, yesCallback將被調用一次,第二次yesCallback將被調用兩次,依此類推。

您也對No按鈕執行相同的操作,但由於這只是隱藏了模式,因此不會真正影響頁面的操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM