将新元素添加到文档模型时如何执行 java 脚本
How to reexecute java script when new elements added to document model
我实现了产品列表页面的分页和过滤。
@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);
}
});
});
});
问题是当加载另一批产品时,以前的按钮也开始侦听事件,当我在调用两次的初始加载游戏事件上单击“购买”时,我最终向服务器发出了多个请求。那我该怎么办?
当你向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>
我刚刚记得我之前被警告过这个问题,解决方案是在“主”页面中使用它
$(document).on("click", ".btn-add-to-basket", function () {
... your code here
});
而不是 $(.btn-add-to-basket).click( function () {...} );
在部分视图中
P.S。对于将来遇到此问题的人,对于更清晰的问题标题有什么建议吗?
我认为最好的方法是事件委托。
jQuery Docs - .on() 方法
示例:
$( "#dataTable tbody" ).on( "click", "tr", function() {console.log( $( this).text() );});
最好不要“听”文档对象,而要“听”包装动态元素的容器。
您还可以从这里了解它在 JS 中的工作原理:
Event Delegation in JavaScript
我实现了产品列表页面的分页和过滤。
@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);
}
});
});
});
问题是当加载另一批产品时,以前的按钮也开始侦听事件,当我在调用两次的初始加载游戏事件上单击“购买”时,我最终向服务器发出了多个请求。那我该怎么办?
当你向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>
我刚刚记得我之前被警告过这个问题,解决方案是在“主”页面中使用它
$(document).on("click", ".btn-add-to-basket", function () {
... your code here
});
而不是 $(.btn-add-to-basket).click( function () {...} );
在部分视图中
P.S。对于将来遇到此问题的人,对于更清晰的问题标题有什么建议吗?
我认为最好的方法是事件委托。
jQuery Docs - .on() 方法
示例:
$( "#dataTable tbody" ).on( "click", "tr", function() {console.log( $( this).text() );});
最好不要“听”文档对象,而要“听”包装动态元素的容器。
您还可以从这里了解它在 JS 中的工作原理: Event Delegation in JavaScript