我為帶有產品串列的頁面實作了分頁和過濾。
@model ProductFiltersViewModel
...
<div class="row">
<aside class="col-3">
<nav class="sidebar card py-2 mb-4">
<ul class="nav flex-column" id="nav_accordion">
<form asp-action="LoadGames" id="filters-form">
<input type="hidden" asp-for="PaginationInfo.PageNumber" />
<li class="nav-item">
<div class="container-fluid">
<span>Page Size</span>
<select asp-for="PaginationInfo.PageSize" class="form-select">
<option value="2" selected>2</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
</li>
//Filters here not important for the question//
</form>
</ul>
</nav>
</aside>
<div class="col-9" id="loaded-games">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Placed</th>
<th>Views</th>
<th>Price</th>
<th></th>
</tr>
</thead>
<tbody id="loaded-games-rows">
</tbody>
</table>
</div>
<div id="paging-control" style="display: none;">
<button class="btn btn-success btn-load-games">Load more</button>
</div>
</div>
</div>
@section Scripts
{
<script type="text/javascript" src="js/LoadGames.js"></script>
...
}
因此,當我單擊“加載更多”按鈕時,jquery 會執行 ajax 請求,獲取一定數量的產品(部分視圖)并將它們放在頁面的末尾。
$(document).ready(function () {
loadGames($("form#filters-form"), true);
$(".btn-load-games").click(function () {
var form = $("form#filters-form");
loadGames(form);
});
function loadGames(form, isInitial = false) {
$.ajax({
type: "POST",
url: "/games",
data: form.serialize(),
success: function (response) {
$("tbody#loaded-games-rows").append(response);
incrementPageNumber();
if (isInitial && !checkAndDisplayMessageIfNoGamesFound(response)) {
$("div#paging-control").show();
}
checkIfAllSuitedGamesAlreadyLoaded(response);
},
error: function (response) {
alert(response.responseText);
}
});
}
});
此部分視圖包含產品的原始資料,每個原始資料都有一個“購買”按鈕。
@model List<ProductDetailsViewModel>
@foreach (var item in Model)
{
<tr>
...
<td class="align-middle">
<div class="d-flex justify-content-end">
@if (item.Discontinued || item.UnitsInStock < 1)
{
<button class="btn-add-to-basket btn btn-success" disabled>Buy</button>
}
else
{
<button class="btn-add-to-basket btn btn-success" gamekey="@item.Key">Buy</button>
}
...
</div>
</td>
</tr>
}
<script type="text/javascript" src="js/AddGameToBasket.js"></script>
帶有 jquery 的腳本附加到這個部分視圖,它發送一個 ajax 請求,并在點擊購買按鈕時將產品添加到籃子里。(順便說一句,我無法將此腳本附加到主視圖,因為產品尚未加載并且 DOM 模型上沒有“購買”按鈕,因此當我單擊按鈕時,什么也沒有發生)。
$(document).ready(function () {
$(".btn-add-to-basket").click(function () {
var gamekey = $(this).attr("gamekey");
$.ajax({
type: "POST",
url: "/game/" gamekey "/buy",
data: gamekey,
success: function (response) {
alert("Added to basket");
},
error: function (response) {
alert(response.responseText);
}
});
});
});
問題是當另一堆產品被加載時,前面的按鈕也開始監聽事件,當我在初始加載的游戲事件上單擊“購買”兩次時,我最終收到了對服務器的多個請求。那我能做什么?
uj5u.com熱心網友回復:
我認為您最好的方法是事件委托。
jQuery 檔案- .on() 方法
例子:
$( "#dataTable tbody" ).on( "click", "tr", function() {console.log( $( this).text() );});
最好不要“聽”檔案物件,而是“聽”包裝動態元素的容器。
您也可以從這里了解它在 JS 中的作業原理: JavaScript 中的事件委托
uj5u.com熱心網友回復:
向DOM添加動態元素時,需要將它們附加到事件監聽器中,可以在創建時完成以避免雙重事件附加,這里是一個例子
$('#noevent').click(function(){
let btn=document.createElement('button');
btn.textContent ='No';
$('.container').append(btn)
})
$('#event').click(function(){
let btn=document.createElement('button');
btn.textContent ='Yes';
//The new event listener
$(btn).click(function(){
console.log('YES!!')
})
$('.container').append(btn)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id='noevent'>No event</button><button id='event'>With event</button>
<div class='container'></div>
uj5u.com熱心網友回復:
我只記得我之前被警告過這個問題,解決方案是在“主”頁面中使用它
$(document).on("click", ".btn-add-to-basket", function () {
... your code here
});
而不是$(.btn-add-to-basket).click( function () {...} );區域視圖
PS 對于將來遇到此問題的人,對更清晰的問題標題有什么建議嗎?
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/381400.html
標籤:javascript 查询 阿贾克斯 dom dom事件
