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

无需setTimeout解决focusout与keydown事件冲突问题及原因

事件冲突原因及解决方案

冲突产生的原因

当按下未按住Shift的Enter键时,事件触发逻辑和DOM操作会导致双重执行:

  1. 首先触发textarea的keydown事件,执行回调里的任务更新和页面渲染逻辑。
  2. 渲染逻辑会移除当前页面的.content元素(包含目标textarea),而DOM元素被从文档树中移除时,浏览器会自动触发该元素的focusout事件,导致同一个回调函数被再次调用。
  3. 两次同步执行的更新和渲染逻辑会导致重复操作数据、重复修改DOM,进而引发异常。

不用setTimeout的解决方法

方法1:添加标志位阻止重复执行

通过一个布尔变量标记是否正在处理逻辑,避免同一操作触发的两次事件重复执行:

// Page content class
const descriptionInput = document.createElement('textarea');
let isUpdating = false; // 新增标志位
const handleDescription = function(e){
    if (isUpdating) return; // 正在处理则直接返回

    const shouldProcess = (e.key === "Enter" && !e.shiftKey) || (e.type === "focusout");
    if (shouldProcess) {
        isUpdating = true;
        // 可选:阻止Enter默认的换行行为
        if (e.key === "Enter") e.preventDefault();
        
        task.description = this.value;
        storage.updateTask(task.id, task);
        (new Render).refreshPage();
        
        isUpdating = false;
    }
}
descriptionInput.addEventListener('keydown', handleDescription)
descriptionInput.addEventListener('focusout', handleDescription)

方法2:拆分事件回调并动态解绑

将keydown和focusout的逻辑拆分,在keydown触发后解绑focusout事件,避免元素被移除时触发重复逻辑:

// Page content class
const descriptionInput = document.createElement('textarea');

// 提取公共逻辑
const updateTaskAndRefresh = function() {
    task.description = this.value;
    storage.updateTask(task.id, task);
    (new Render).refreshPage();
}

// 单独处理keydown事件
const handleKeydown = function(e){
    if (e.key === "Enter" && !e.shiftKey) {
        e.preventDefault(); // 阻止换行
        updateTaskAndRefresh.call(this);
        // 解绑focusout事件,避免元素被移除时触发
        this.removeEventListener('focusout', handleFocusout);
    }
}

// 单独处理focusout事件
const handleFocusout = function(){
    updateTaskAndRefresh.call(this);
}

descriptionInput.addEventListener('keydown', handleKeydown)
descriptionInput.addEventListener('focusout', handleFocusout)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 11:25:12