点击外部时 textarea 无法 blur 的根本原因是 layui 等框架干扰原生焦点流,可靠解法是监听 document 点击事件,通过判断点击目标是否在编辑容器外,主动触发 blur 并执行后续逻辑。

点击外部时 textarea 无法 blur?先确认是否绑对了事件源
直接给 textarea 绑 blur 事件没用,因为点击外部时焦点确实会离开,但你往往需要「在失焦瞬间做点事」(比如保存、校验、收起编辑态),而原生 blur 在 Layui 表格或弹窗里常被拦截或延迟触发。真正可靠的做法是监听全局点击,再判断目标是否在当前 textarea 及其父容器之外。
如何用 document 点击事件安全检测 textarea 失焦
不能只靠 textarea.blur,Layui 的表格单元格编辑、layer 弹窗、动态渲染都会干扰原生焦点流。必须手动判定「点击是否落在编辑区域外」:
- 给正在编辑的
textarea所在单元格或容器加一个临时 class,比如editing-textarea - 在
document上绑定一次click监听,用e.target判断是否点击在该 class 容器内 - 若不在,且当前有活跃的
textarea,就主动调用.blur()并执行后续逻辑 - 注意:必须用
$(document).one('click', ...)或配合标记位防重复触发,否则每次点击都执行
表格中双击编辑 textarea 后,点击其他行不自动 blur 怎么办
Layui 表格的 edit 事件只管值变更,不管焦点管理。双击进入编辑后,textarea 插入 DOM,但 Layui 不接管它的 blur 生命周期。常见表现是:点另一行单元格,新行开始编辑,但旧 textarea 还挂着,没触发保存或验证。
- 在
table.on('edit')回调里,第一行就记录当前编辑的textarea和所在tr,比如存到变量currentEditEl - 同时监听
table.on('cell'),只要点击的是非编辑单元格,就先对currentEditEl调用.blur(),再清空变量 - 别依赖
focusout——它在表格里常因快速切换而丢失事件目标 - 如果用了自定义模板(如
templet: function(d) { return '<textarea>'+ d.content +'</textarea>' }),必须确保每次插入后手动绑定blur,且绑定前移除旧监听
layer 弹窗里的 textarea 点击遮罩层不 blur?要绕过 shade 拦截
Layer 默认遮罩层(.layui-layer-shade)会吞掉点击事件,导致 textarea 收不到 blur。这不是浏览器问题,是 Layui 主动阻止了遮罩层上的交互冒泡。
- 不要等遮罩层 click 后再 blur,而是监听
layero.find('.layui-layer-shade').on('click', ...) - 更稳妥的方式:在
layer.open的success回调里,对弹窗内的textarea绑定blur,并同时监听layero.on('click', function(e) { if (!$(e.target).closest('textarea').length) { ... } }) - 关键细节:检查
e.target是否为textarea或其子元素(比如里面套了span做高亮),要用$(e.target).closest('textarea').length > 0判定 - 移动端需额外加
touchend,iOS Safari 对 click 延迟敏感,单靠 click 可能漏触发
真正难的不是写几行 blur,而是判断「此刻用户是不是真想结束编辑」——光标移走、点击空白、切到别的 tab、甚至按 Esc,每种场景的 DOM 状态和事件路径都不一样。Layui 不提供统一焦点生命周期钩子,得自己搭一层状态机来兜底。











