textarea输入后submit按钮仍无法启用的技术问题求助
问题:文本框输入内容后提交按钮仍保持禁用状态
我有一个包含textarea和submit按钮的表单,需求是根据textarea内是否有输入来启用或禁用submit按钮,已确认能够正确选中submit按钮与textarea元素。当前使用Django框架,相关代码如下:
JS代码
document.addEventListener('DOMContentLoaded',() => { document.querySelector('#all-posts').addEventListener('click', () => loadAllPosts()) if (document.querySelector('#following') != null){ document.querySelector('#following').addEventListener('click', () => loadFollowing()) } loadAllPosts(); }); function loadAllPosts(){ document.querySelector('#allPosts-view').style.display = 'block'; document.querySelector('#following-view').style.display = 'none'; fetch('/api/post') .then(response => response.json()) .then(data => { const posts = data.data.posts; const postCards = posts.map(post => { let likeBtnClass = 'fa fa-heart-o'; if (post.liked_by_user) { likeBtnClass = 'fa fa-heart'; } const on = new Date(post.posted_on).toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', month: 'long', day: 'numeric', year: 'numeric', timeZone: 'UTC' }); return ` <div class="card text-white bg-dark mb-3" style="margin-bottom: 5px;"> <div class="card-body"> <h5 class="card-title">${post.posted_by.username}</h5> <p class="card-subtitle mb-2 text-muted" style="font-size: 12px;">${on}</p> <hr style="border: none; height: 1px; background-color: #FFFFF0; margin: 0px;"> <p class="card-text" style="margin-top: 5px; font-size: 25px;">${post.content}</p> <div class="like-container"> <i id="like-btn" class="${likeBtnClass}" style="font-size:24px; cursor:pointer; margin-right: 10px;"></i> <p class="card-subtitle mb-2 text-muted" style="margin-top: 0.5rem; padding: 0px; font-size: 12px;">${post.likes}</p> </div> </div> </div> `; }); document.querySelector('#allPosts-view').innerHTML += postCards.join(''); }) .catch(err => console.error(err)); const likeBtnsContainer = document.querySelector('#allPosts-view'); likeBtnsContainer.addEventListener('click', (event) => { if (event.target.matches('#like-btn')) { event.target.classList.toggle('fa-heart'); event.target.classList.toggle('fa-heart-o'); } }); if (document.querySelector('#newPost-form') !== null) { const submit = document.querySelector('#newPost-submit'); const content = document.querySelector('#newPost-content'); submit.disabled = true; content.addEventListener('keyup', () => { if (content.value.length > 0) { submit.disabled = false; } else { submit.disabled = true; } }); } } function loadFollowing() { document.querySelector('#allPosts-view').style.display = 'none'; document.querySelector('#following-view').style.display = 'block'; }
HTML代码
{% extends "network/layout.html" %} {% load static %} {% block title %} Index {% endblock %} {% block js %} <script src="{% static 'network/index.js' %}"></script> {% endblock %} {% block body %} <div id="allPosts-view"> {% if request.user.is_authenticated %} <div class="card text-white bg-dark mb-3" style="padding: 15px; margin-bottom: 5px;" > <form id="newPost-form"> <div class="form-group"> <label for="NEW-POST" style="font-size: 20px;">New Post</label> <hr style="border: none; height: 1px; background-color: #FFFFF0; margin: 0px 0px 15px 0px;"> <textarea class="form-control" id="newPost-content" rows="3" style="resize: none; height: 120px;"></textarea> </div> <input id="newPost-submit" type="submit" class="btn btn-primary" style="background-color: #007BFF;" value="Post"> </form> </div> {% endif %} </div> <div id="following-view"> </div> {% endblock %}
问题现象
submit按钮初始状态已设置为禁用,但在textarea中输入内容后,按钮仍处于禁用状态,无法正常启用。
解决方案
问题核心是DOM元素被覆盖导致事件监听失效,加上事件类型选择不够全面,以下是修复后的代码和说明:
修复后的JS代码
document.addEventListener('DOMContentLoaded',() => { document.querySelector('#all-posts').addEventListener('click', () => loadAllPosts()) if (document.querySelector('#following') != null){ document.querySelector('#following').addEventListener('click', () => loadFollowing()) } // 单独初始化表单监听,避免被后续DOM操作影响 initFormListener(); loadAllPosts(); }); // 抽离表单监听逻辑 function initFormListener() { const form = document.querySelector('#newPost-form'); if (!form) return; const submit = form.querySelector('#newPost-submit'); const content = form.querySelector('#newPost-content'); // 初始化禁用状态(排除纯空格情况) submit.disabled = !content.value.trim(); // 使用input事件,覆盖粘贴、拖拽等所有输入场景 content.addEventListener('input', () => { // 判断是否为有效输入(非纯空格) submit.disabled = content.value.trim().length === 0; }); } function loadAllPosts(){ document.querySelector('#allPosts-view').style.display = 'block'; document.querySelector('#following-view').style.display = 'none'; // 先保存表单容器,避免被innerHTML覆盖 const formContainer = document.querySelector('#newPost-form')?.parentElement; fetch('/api/post') .then(response => response.json()) .then(data => { const posts = data.data.posts; const postCards = posts.map(post => { let likeBtnClass = 'fa fa-heart-o'; if (post.liked_by_user) { likeBtnClass = 'fa fa-heart'; } const on = new Date(post.posted_on).toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', month: 'long', day: 'numeric', year: 'numeric', timeZone: 'UTC' }); return ` <div class="card text-white bg-dark mb-3" style="margin-bottom: 5px;"> <div class="card-body"> <h5 class="card-title">${post.posted_by.username}</h5> <p class="card-subtitle mb-2 text-muted" style="font-size: 12px;">${on}</p> <hr style="border: none; height: 1px; background-color: #FFFFF0; margin: 0px;"> <p class="card-text" style="margin-top: 5px; font-size: 25px;">${post.content}</p> <div class="like-container"> <i class="like-btn ${likeBtnClass}" style="font-size:24px; cursor:pointer; margin-right: 10px;"></i> <p class="card-subtitle mb-2 text-muted" style="margin-top: 0.5rem; padding: 0px; font-size: 12px;">${post.likes}</p> </div> </div> </div> `; }); const allPostsView = document.querySelector('#allPosts-view'); // 先清空容器 allPostsView.innerHTML = ''; // 把表单放回容器顶部 if (formContainer) { allPostsView.appendChild(formContainer); } // 再追加帖子内容 allPostsView.innerHTML += postCards.join(''); }) .catch(err => console.error(err)); const likeBtnsContainer = document.querySelector('#allPosts-view'); likeBtnsContainer.addEventListener('click', (event) => { // 修正重复id问题,改用class选择器 if (event.target.matches('.like-btn')) { event.target.classList.toggle('fa-heart'); event.target.classList.toggle('fa-heart-o'); } }); } function loadFollowing() { document.querySelector('#allPosts-view').style.display = 'none'; document.querySelector('#following-view').style.display = 'block'; }
关键修改说明
- 分离表单监听逻辑:将表单的事件绑定放在
initFormListener函数中,在DOM加载完成后直接执行,避免被loadAllPosts里的DOM操作覆盖。 - 更换事件类型:用
input事件替代keyup,覆盖粘贴、拖拽文本等所有输入场景,同时用trim()判断内容是否为有效输入(排除纯空格的无效内容)。 - 避免DOM元素被覆盖:在
loadAllPosts中先保存表单的父元素,清空容器后重新添加表单,再追加帖子内容,保证原表单DOM不被替换,事件监听持续有效。 - 修正重复ID问题:原代码中所有点赞按钮使用相同的
id="like-btn",违反HTML规范,改为class选择器.like-btn,避免事件绑定冲突。
内容的提问来源于stack exchange,提问作者Rohan Benny
相关产品推荐
相关产品推荐

