我在<textarea>
内有<button>
和<form>
。提交后,我致电e.preventDefault()
并通过AJAX
提交表单。在那里,我返回查询并PREPEND
查看此列表顶部<div>
内的信息。
此外,我已经为每个项目提供了删除功能,这在客户端是即时的,但也通过AJAX
提交表单以完全删除。这有点工作。
当用户加载页面时,会立即查询存储在数据库中的项目并将其添加到屏幕中。
继续,在第一个代码示例中找到const delPostFunc
。这是一个立即调用的匿名函数,以确保最初添加到屏幕的任何项目都被分配了click
事件处理程序。
当用户通过submitPostBtn.addEventListener('click', e => {
提交新项目时,在第一个示例的底部,会进行两次调用。第二个示例中为const submitPost
,AJAX
,第二个示例中为const returnNewestPost
,AJAX
。这个returnNewestPost
调用会从数据库中返回一些DATA
,这恰好是插入的最新项目,然后PREPENDS
此项目位于列表顶部,{{1}最后调用displayPostWrapper.prepend(newPostDiv);
函数以尝试将事件处理程序重新分配给新插入的项。这是因为delPostFunc();
删除了应该在元素上的任何事件处理程序,或者这是我所相信的。
innerHTML
// DELETE POST VARIABLES
let deletePostBtn = document.querySelectorAll('button[name="delete_post"]');
const displayPostWrapper = document.querySelector('.col-8.pt-4');
let displayPostSection = document.querySelectorAll('.col-8.pt-4 .row');
let postID = document.querySelectorAll('#delete-post-id');
// SUBMIT POST VARIABLES
const submitPostBtn = document.querySelector('#submit-post-button');
const submitPostID = document.querySelector('#submit-post-id');
const submitPostContent = document.querySelector('#submit-post-content');
const submitPostName = document.querySelector('#submit-post-name');
// MAKING THE CALL TO DELETE THE POST
const delPostFunc = () => {
console.log(deletePostBtn);
deletePostBtn = document.querySelectorAll('button[name="delete_post"]');
console.log(deletePostBtn);
if (deletePostBtn) {
for (let i = 0; i < deletePostBtn.length; i++) {
deletePostBtn[i].addEventListener('click', e => {
e.preventDefault();
postID = document.querySelectorAll('#delete-post-id');
displayPostSection = document.querySelectorAll('.col-8.pt-4 .row');
console.log(postID[i].value);
// ${postID[i]} comes from `const postID` at the top
deletePostPromise('http://localhost/mouthblog/ajax/delete_post.ajax.php', `id=${postID[i].value}`);
console.log(deletePostBtn);
displayPostSection[i].remove();
console.log(deletePostBtn);
});
}
}
}
// CALL `delPostFunc()` FOR THE INITIAL `deletePostBtn` ON SCREEN
delPostFunc();
// MAKING CALL TO SUBMIT NEW POST
if (submitPostBtn) {
submitPostBtn.addEventListener('click', e => {
e.preventDefault();
// SUBMIT POST
submitPost('http://localhost/mouthblog/ajax/submit_post.ajax.php',
`id=${submitPostID.value}&name=${submitPostName.value}&content=${submitPostContent.value}`)
.then(() => {
// RETURN THAT SAME POST
returnNewestPost('http://localhost/mouthblog/api/newest_post.php')
.then(data => {
// INSERT POST INTO DOM
const newPostDiv = document.createElement('div');
newPostDiv.setAttribute('class', 'row');
newPostDiv.innerHTML = `
<article class="col-10 offset-1">
<h2 class="h2">${data.user_name}</h2>
<small>${data.date_created}</small>
<form action="//localhost/mouthblog/blog.php" method="POST">
<button class="btn btn-danger" name="delete_post" type="submit">DELETE</button>
<input id="delete-post-id" name="post_id" type="hidden" value="${data.id}">
</form>
<hr>
<p class="lead">${data.content}</p>
</article>
`;
console.log(`INSERTING ${data.id}`);
displayPostWrapper.prepend(newPostDiv);
console.log(`INSERT ${data.id} COMPLETE`);
// GIVE THE `newPostDiv`'s `delete button` THE CLICK EVENT HANDLER
console.log(`RUNNING delPostFunc()`);
delPostFunc(); // BOOM!
console.log(`delPostFunc() COMPLETE`);
});
});
});
}
答案 0 :(得分:0)
这个问题的最简单答案是使用Event Delegation重写脚本。
事件委托允许我们将单个事件侦听器附加到父元素,该元素将为匹配选择器的所有后代触发,无论这些后代现在是存在还是将来添加。
比较OP中的脚本并比较一下。重写的脚本具有更少的代码,更少的循环,更少的变量,并且更易于维护和阅读。
如果您想比较细节,事件委托会从error: implicit instantiation of undefined template 'std::__1::hash<std::__1::vector<int, std::__1::allocator<int> > >'
if (displayPostWrapper && submitPostBtn) {