You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS输入为空时Keyup事件无法清理DOM及退格键重复渲染问题排查

问题分析与修复方案

核心问题

  1. 异步请求竞态:每次按键都会发起新的fetch请求,旧请求未完成时,新请求的结果会追加到DOM,导致重复渲染。
  2. DOM操作目标错误:代码中反复清空tbody(对应table_body元素),但实际搜索结果是直接追加到tableOutput的innerHTML中,两者不匹配,清空操作完全无效;同时直接修改tableOutput的innerHTML会覆盖表头,且未正确清空历史结果。
  3. 退格键处理冗余:针对Backspace的清空操作作用在错误元素上,没有实际效果。

修复步骤

1. 处理请求竞态:用AbortController取消旧请求

每次发起新请求前,取消上一次未完成的请求,避免旧结果干扰新搜索结果的渲染。

2. 修正DOM操作逻辑

  • 搜索结果渲染到table_body(代码中的tbody变量)内,而非直接修改tableOutput,这样既保留表头,又能确保清空操作有效。
  • 无搜索结果时,仅在table_body内显示提示,不破坏整个表格结构。

3. 移除无效代码

删除针对Backspace的无用清空逻辑,统一在请求发起前清空目标容器。

修正后的完整代码

JavaScript

const searchField = document.getElementById('search_field');
const tableOutput = document.getElementById('table_output');
const tableApp = document.getElementById('table_app');
const tbody = document.getElementById('table_body');
let abortController = null; // 管理请求取消

searchField.addEventListener('keyup', (e) => {
    const searchValue = e.target.value.trim();

    // 取消上一次未完成的请求
    if (abortController) {
        abortController.abort();
    }

    // 清空结果容器
    tbody.innerHTML = '';

    if (searchValue.length > 0) {
        abortController = new AbortController();
        fetch('filtered_tasks', {
            body: JSON.stringify({ searchText: searchValue }),
            method: 'POST',
            signal: abortController.signal // 绑定取消信号
        })
        .then(res => res.json())
        .then(data => {
            console.log(data);
            tableApp.style.display = 'none';
            tableOutput.style.display = 'table';
            
            if(data.length === 0) {
                tbody.innerHTML = '<div class="row"><div class="cell" colspan="12">Nessun risultato trovato</div></div>';
            }else {
                // 一次性拼接所有HTML,提升性能
                let rowsHtml = '';
                data.forEach(task => {
                    let rowClass = '';
                    if(task.delayed === 1){
                        rowClass = 'warning-1';
                    }else if (task.delayed === 2){
                        rowClass = 'warning-2';
                    }else if (task.delayed > 2){
                        rowClass = 'warning-3';
                    }
                    // 复用模板减少冗余
                    rowsHtml += `
                        <div class="row ${rowClass}">
                            <div class="cell">${task.a}</div>
                            <div class="cell">${task.b}</div>
                            <div class="cell">${task.c}</div>
                            <div class="cell">${task.d}</div>
                            <div class="cell">${task.e}</div>
                            <div class="cell">${task.f}</div>
                            <div class="cell">${task.g}</div>
                            <div class="cell">${task.h}</div>
                            <div class="cell"><a href="tel:${task.i}"> ${task.i}</a></div>
                            <div class="cell">${task.e}</div>
                            <div class="cell">${task.f}</div>
                            <div class="cell">${task.g}</div>
                        </div>
                    `;
                 });
                 tbody.innerHTML = rowsHtml;
            }
        })
        .catch(err => {
            // 忽略请求取消的错误
            if (err.name !== 'AbortError') {
                console.error('请求出错:', err);
            }
        });
   }else {
        tableOutput.style.display = 'none';
        tableApp.style.display = 'table';
   }
})

补充说明

  • 新增AbortController管理请求,彻底解决旧请求干扰新结果的问题。
  • 简化重复的HTML模板逻辑,通过判断rowClass复用代码,减少冗余。
  • 一次性拼接所有结果HTML再赋值,比多次+=性能更优,也避免了部分渲染的异常。
  • 无结果提示保留表格结构,用colspan="12"让文本占满整行。

额外优化建议

  • 添加输入防抖(debounce),设置300ms延迟,用户停止输入后再发起请求,减少服务器压力。
  • 对task属性值做转义处理,避免XSS攻击风险。

内容的提问来源于stack exchange,提问作者Federico Iannarelli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 07:25:32