编辑帖子按钮onclick函数仅运行一次的问题求助
问题:帖子编辑按钮首次点击正常,再次点击无响应
点击帖子的编辑按钮,第一次可正常触发编辑流程并更新内容,但再次点击该按钮时,onclick函数完全不执行。
HTML代码
<div class="post"> <b><a href="{% url 'profile' post.author.id %}">{{post.author}}</a></b> <input type="hidden" name="postid" value={{post.id}}> <!-- <br><br> --> <p>{{post.content}}</p> {% csrf_token %} <textarea name="edit_content" id="edit_content" cols="50" rows="5"></textarea> {% if user.is_authenticated %} {% if post.author == user %} <button class="edit" onclick="edit(this)">Edit</button> {% endif %} {% endif %} <p><small class="text-muted">{{post.created_on}}</small></p> </div>
注:textarea默认设置display: none
JavaScript代码(原代码)
function edit(ele){ var parent = ele.parentNode; console.log(ele.parentNode); var post = parent.querySelector('p'); var textarea = parent.querySelector('textarea'); var id = parent.querySelector('input'); post.style.display = 'none'; textarea.style.display = 'block'; ele.innerHTML = "Save"; ele.id = "save"; ele.disabled = true; const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value; textarea.onkeyup = () => { if( textarea.value.length > 0){ ele.disabled = false; } else{ ele.disabled = true; } } var save = document.getElementById('save'); save.onclick = () => { fetch("http://127.0.0.1:8000/edit", { method : "PUT", headers: {'X-CSRFToken': csrftoken}, body : JSON.stringify({ "postdata" : textarea.value, "id" : id.value }) }).then(() => { post.innerHTML = textarea.value; // textarea.value = ''; post.style.display = "block"; textarea.style.display = "none"; ele.innerHTML = "Edit"; save.removeAttribute('id'); }); }
问题根源
第一次点击编辑按钮时,代码给按钮绑定了新的onclick保存逻辑,这会直接覆盖按钮原本的edit()点击事件。保存完成后,仅将按钮文本改回"Edit",但未恢复原本的onclick="edit(this)"绑定,导致后续点击无任何函数触发。
此外,原代码中通过getElementById('save')获取按钮存在隐患:若页面有多个帖子,重复设置相同ID会导致DOM元素冲突。
修复方案
放弃通过覆盖onclick切换逻辑的方式,改为在同一个edit函数内根据按钮当前状态(编辑/保存)执行对应操作,同时优化潜在问题:
function edit(ele){ const parent = ele.parentNode; const post = parent.querySelector('p'); const textarea = parent.querySelector('textarea'); const id = parent.querySelector('input[name="postid"]'); // 从当前帖子节点获取CSRF Token,避免多帖子场景下取错 const csrftoken = parent.querySelector('[name=csrfmiddlewaretoken]').value; // 根据按钮文本判断当前状态 if(ele.textContent.trim() === "Edit"){ // 切换到编辑模式 post.style.display = 'none'; textarea.style.display = 'block'; // 把当前帖子内容同步到textarea(原代码缺失此步骤) textarea.value = post.textContent.trim(); ele.textContent = "Save"; // 初始根据内容长度设置按钮禁用状态 ele.disabled = textarea.value.length === 0; } else { // 执行保存操作 fetch("http://127.0.0.1:8000/edit", { method : "PUT", headers: { 'X-CSRFToken': csrftoken, 'Content-Type': 'application/json' }, body : JSON.stringify({ "postdata" : textarea.value, "id" : id.value }) }).then(() => { post.innerHTML = textarea.value; post.style.display = "block"; textarea.style.display = "none"; ele.textContent = "Edit"; }); } // 实时监听输入,控制保存按钮禁用状态 textarea.onkeyup = () => { // 仅在保存状态时触发 if(ele.textContent.trim() === "Save"){ ele.disabled = textarea.value.length === 0; } } }
关键修改点
- 移除动态ID操作,通过按钮文本判断状态,避免DOM ID冲突
- 进入编辑模式时自动同步帖子内容到textarea,提升用户体验
- 从当前帖子节点获取CSRF Token,适配多帖子场景
- 同一个函数处理编辑/保存逻辑,避免事件绑定被覆盖
- 优化按钮禁用状态的初始设置与实时监听逻辑
内容的提问来源于stack exchange,提问作者Harsh
相关产品推荐
相关产品推荐

