JavaScript 实战:基于事件委托与 focus 实现表格单元格点击编辑(Edit TD on Click)
文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载导读本文基于 Modern JavaScript Tutorialen.javascript.info中Edit TD on click一课的官方题解系统讲解如何用原生 JavaScript 为表格单元格实现点击即编辑的交互点击td后原地出现一个大小一致、无边框的textarea单元格下方弹出 OK / CANCEL 按钮用于确认或取消编辑。读完本文你将掌握事件委托event delegation、closest()定位目标、focus()聚焦、以及单实例编辑状态等前端实战技巧并能直接复用完整可运行的实现代码。任务背景需求拆解该任务出自 2-ui/4-forms-controls/2-focus-blur/4-edit-td-click/task.md核心需求如下点击单元格进入编辑态点击td后单元格内出现textarea用户可修改其中的 HTML 内容几何保持不变textarea与单元格同宽同高、无缩放no resize所有布局尺寸与点击前完全一致OK / CANCEL 按钮编辑期间单元格下方出现两个按钮分别用于提交修改与取消编辑同一时刻只允许一个单元格处于编辑态当某个td正在编辑时点击其他单元格应被忽略必须使用事件委托表格可能包含大量单元格不能给每个td单独绑定监听器。官方题解 solution.md 给出了四步核心思路本文将其逐条展开并结合仓库中的完整源码实现进行深度讲解。核心思路一个委托监听器 一个编辑状态所有交互进入编辑、点击 OK、点击 CANCEL、忽略编辑期间的点击都收敛到表格上的唯一一个click监听器这就是事件委托的典型应用——把监听器挂到祖先元素table上用event.target.closest()判断实际点击的目标从而避免为每个td单独注册事件。同时用模块级变量editingTd保存当前正在编辑的单元格及其原始内容作为整个表格的单实例编辑状态let editingTd;这个变量是整个实现的枢纽它既用于在编辑期间拦截其他单元格的点击if (editingTd) return;也用于 CANCEL 时恢复单元格的原始 HTML。四步实现详解官方题解将实现拆成四个步骤下面逐一结合 solution.view/script.js 的代码展开。第 1 步点击时用textarea替换单元格内容点击td后需要用同尺寸、无边框的textarea替换单元格内部内容。关键在于精确计算几何尺寸保证布局不跳动let textArea document.createElement(textarea); textArea.style.width td.clientWidth px; textArea.style.height td.clientHeight px; textArea.className edit-area; td.innerHTML ; td.appendChild(textArea);td.clientWidth/td.clientHeight是不含边框的内容区尺寸正好与textarea的内容盒匹配用className edit-area挂接样式类配合 CSS 去掉边框、边距与缩放手柄详见下文CSS 细节先清空td.innerHTML再appendChild避免残留文本与 textarea 并存。第 2 步把td.innerHTML同步到textarea.value进入编辑态前先把单元格的现有内容可能是包含strong、br的富 HTML作为初始值写入 textareatextArea.value td.innerHTML;注意这里的语义textarea.value中存放的是文本形式的 HTML 字符串。提交时这段文本会作为新 HTML 直接写回td.innerHTML因此用户编辑的是HTML 源码文本而非纯文本——这是该实现的一个重要特性适合简单富内容单元格的快速编辑。同时原始内容被保存在editingTd.data中供 CANCEL 恢复editingTd { elem: td, data: td.innerHTML };第 3 步聚焦 textarea创建 textarea 后立即调用focus()让用户无需再次点击即可直接输入textArea.focus();这里正好呼应父级章节 focus/blur 事件详解 中提到的elem.focus()方法——它用于以编程方式把焦点设置到元素上。textarea属于浏览器默认支持聚焦的表单元素因此focus()可以直接生效无需tabindex。第 4 步在单元格下方渲染 OK / CANCEL 按钮并处理点击用insertAdjacentHTML在单元格末尾追加控制条包含 OK 与 CANCEL 两个按钮td.insertAdjacentHTML(beforeEnd, div classedit-controlsbutton classedit-okOK/buttonbutton classedit-cancelCANCEL/button/div );按钮的处理统一由表格上的委托监听器完成——根据event.target.closest(.edit-cancel,.edit-ok,td)的结果分支点 CANCEL 走finishTdEdit(editingTd.elem, false)点 OK 走finishTdEdit(editingTd.elem, true)。完整实现代码逐段剖析以下为 solution.view/script.js 的完整源码它是官方题解四步思路的最终落地。委托监听器一次监听三分支let table document.getElementById(bagua-table); let editingTd; table.onclick function(event) { // 3 possible targets let target event.target.closest(.edit-cancel,.edit-ok,td); if (!table.contains(target)) return; if (target.className edit-cancel) { finishTdEdit(editingTd.elem, false); } else if (target.className edit-ok) { finishTdEdit(editingTd.elem, true); } else if (target.nodeName TD) { if (editingTd) return; // already editing makeTdEditable(target); } };这段代码有四个值得注意的工程细节closest(.edit-cancel,.edit-ok,td)一次命中三类目标按钮、单元格甚至按钮内部可能的子元素都能被正确归约到所属容器省去逐级parentNode遍历table.contains(target)兜底校验防止点击表格外部时进入分支比如点击th表头或其他区域按钮判断用className精确匹配由于按钮没有额外 classtarget.className恰好等于edit-ok/edit-cancelif (editingTd) return;实现单编辑实例只要已有单元格处于编辑态点击任何其他td都会被静默忽略满足任务同时只有一个单元格可编辑的硬性要求。进入编辑态makeTdEditablefunction makeTdEditable(td) { editingTd { elem: td, data: td.innerHTML }; td.classList.add(edit-td); // td is in edit state, CSS also styles the area inside let textArea document.createElement(textarea); textArea.style.width td.clientWidth px; textArea.style.height td.clientHeight px; textArea.className edit-area; textArea.value td.innerHTML; td.innerHTML ; td.appendChild(textArea); textArea.focus(); td.insertAdjacentHTML(beforeEnd, div classedit-controlsbutton classedit-okOK/buttonbutton classedit-cancelCANCEL/button/div ); }editingTd在此被赋值为一个对象同时保存元素引用与原始 HTML 快照——这正是取消编辑时能完美还原的前提。classList.add(edit-td)给单元格打上编辑态标记CSS 据此把单元格设为position: relative为下方绝对定位的控制条提供定位基准。结束编辑态finishTdEditfunction finishTdEdit(td, isOk) { if (isOk) { td.innerHTML td.firstChild.value; } else { td.innerHTML editingTd.data; } td.classList.remove(edit-td); editingTd null; }OK 提交td.firstChild就是唯一的textarea其value属性中的文本被当作 HTML 写回td.innerHTMLCANCEL 取消从editingTd.data取回进入编辑态时保存的原始 HTML完全还原单元格无论哪种路径最后都移除edit-td类并置空editingTd释放编辑状态允许下一个单元格进入编辑。CSS 细节几何不变与按钮定位编辑态的外观完全由 solution.view/my.css 控制它承担了任务中no resize、几何保持不变的视觉要求.edit-td .edit-area { border: none; margin: 0; padding: 0; display: block; /* remove resizing handle in Firefox */ resize: none; /* remove outline on focus in Chrome */ outline: none; /* remove scrollbar in IE */ overflow: auto; } .edit-controls { position: absolute; } .edit-td { position: relative; padding: 0; }逐条解读resize: none禁用 textarea 右下角的拖拽缩放手柄Firefox 特有保证尺寸只由 JS 写入的宽高决定outline: none去掉聚焦时的描边Chrome 默认会给聚焦的 textarea 加轮廓避免视觉突兀overflow: auto去掉 IE 下多余滚动条的显示过长的内容仍可滚动查看不影响布局.edit-td { position: relative; padding: 0; }单元格自身成为定位上下文且清除内边距让 textarea 精确铺满原内容区.edit-controls { position: absolute; }控制条脱离文档流叠放在单元格正下方不影响表格行高。页面结构 solution.view/index.html 是一张八卦图Bagua Chart表格9 个数据单元格由bagua.csssolution.view/bagua.css着色任务起点是 source.view/script.js 中留空的/* your code */骨架读者可以自行先尝试实现再对照题解验证。设计要点复盘为什么不用 focus/blur 完成单编辑实例一个常见的替代思路是进入编辑时给 textarea 注册blur事件失焦即结束编辑。但官方实现刻意选择了委托 click 显式按钮方案原因可从 focus/blur 章节 中归纳blur触发时机难以精确控制点击 CANCEL 按钮会使 textarea 失焦从而提前结束编辑与CANCEL 恢复原始内容的语义冲突focus/blur不冒泡若想监听整个表格的焦点变化必须依赖捕获阶段或focusin/focusout复杂度更高点击其他单元格时由于编辑态已通过if (editingTd) return;拦截根本不会触发第二次编辑行为完全确定。事件委托的价值任务明确要求表格可能有很多单元格使用事件委托。委托的核心收益是无论表格有 9 个还是 900 个单元格都只需一个table.onclick新增单元格也无需重新绑定。closest()是委托定位的标准工具——它在 DOM 树中从event.target向上查找命中.edit-cancel、.edit-ok或td中的任意一个即返回。状态变量的职责分离editingTd.elem当前编辑的单元格引用供finishTdEdit直接操作editingTd.data原始 HTML 快照供 CANCEL 还原editingTd非空即代表编辑进行中同时充当互斥锁。三者合一用最少的全局状态完成了编辑中拦截 取消恢复两大功能。小结Edit TD on click 是理解前端交互编程的经典案例它把四个核心知识点浓缩在几十行代码里事件委托单一监听器处理进入编辑、OK、CANCEL 三类点击closest()精准归约目标几何保真clientWidth/clientHeight配合resize: none、border: none实现无跳动替换焦点管理textarea.focus()让编辑态无缝衔接用户输入同时巧妙规避了focus/blur不冒泡、时机难控的问题状态快照editingTd.data保存原始 HTML使取消编辑成为零成本的回退操作。完整可运行示例位于 solution.view/index.html配合 solution.view/script.js 与 solution.view/my.css 即可在本地直接打开体验。若想进一步理解背后的 focus/blur 机制包括tabindex、捕获阶段委托与focusin/focusout可继续阅读 2-ui/4-forms-controls/2-focus-blur/article.md 的完整章节。赞分享文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载相关推荐Litestream 如何复制 SQLiteWAL 监控与增量备份机制全揭秘Litestream 如何复制 SQLiteWAL 监控与增量备份机制全揭秘 Litestream 是一款专为 SQLite 打造的流式复制Streamin文档/教程前端PHPStan 错误标识符 parameter.superglobal 全解析杜绝以超全局变量命名函数参数PHPStan 错误标识符 parameter.superglobal 全解析杜绝以超全局变量命名函数参数 本篇文章以 PHPStan 官方错误文档 webs文档/教程前端JavaScript 事件委托实战基于事件委托实现可折叠树形菜单Sliding TreeJavaScript 事件委托实战基于事件委托实现可折叠树形菜单Sliding Tree 事件委托Event Delegation是 DOM 事件处理文档/教程前端上一篇【亲测免费】 PokeMMO 项目教程下一篇gofeed 完全指南如何在 Go 中高效解析 RSS、Atom 和 JSON Feed创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Linux 系统 常用命令(持续更新)

Linux 系统 常用命令(持续更新)

1、要从Linux的Root用户回到普通用户的命令行,可以按照以下步骤进行操作: 1.1 退出Root用户: 在Root用户下,可以使用exit或logout命令退出Root权限,返回到上一级用户(例如 普通用户)的命令行界…

2026/10/16 1:52:59 阅读更多 →
锁相环PLL核心知识:从环路原理到相位噪声与工程调试

锁相环PLL核心知识:从环路原理到相位噪声与工程调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 6:04:18 阅读更多 →
STM32参考设计资源全攻略:官方渠道、社区平台与实战避坑指南

STM32参考设计资源全攻略:官方渠道、社区平台与实战避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:40:09 阅读更多 →

最新新闻

51单片机贪吃蛇实战:12864驱动、EEPROM掉电保存与嵌入式分层设计

51单片机贪吃蛇实战:12864驱动、EEPROM掉电保存与嵌入式分层设计

简介:本资源是一套面向大学本科课程设计的51单片机贪吃蛇游戏完整开发方案,适用于单片机原理与应用、嵌入式系统实践等课程学习与项目实训。资源包含Proteus仿真工程(.pdsprj)、Keil C51源码(.c/.a51)、编译…

2026/10/21 3:32:25 阅读更多 →
图书推荐系统实战:Python协同过滤从原理到代码避坑指南

图书推荐系统实战:Python协同过滤从原理到代码避坑指南

我记得第一次带学生跑这个图书推荐系统项目时,好几个人卡在了同一个地方:代码能跑通,但推荐结果全是乱的。后来查了半天,问题出在一个被注释掉的函数上。这个项目在中文互联网上流传了很多版本,绝大多数人拿到的都是简…

2026/10/21 3:32:25 阅读更多 →
空间注意力模块实战指南:原理、代码与调参经验

空间注意力模块实战指南:原理、代码与调参经验

做视觉任务这些年,大家都会遇到一个很实际的需求:网络深了、宽了,但该学的东西没学会。SpatialAttention空间注意力模块,是我调过的结构里性价比最高的一个——代码就几十行、参数量几乎可以忽略,却能明显改变网络的关…

2026/10/21 3:32:25 阅读更多 →
awesome-shizuku vs Dhizuku:两大Android权限提升工具终极对比指南

awesome-shizuku vs Dhizuku:两大Android权限提升工具终极对比指南

awesome-shizuku vs Dhizuku:两大Android权限提升工具终极对比指南 在Android开发的世界中,awesome-shizuku和Dhizuku是两个备受关注的高权限工具,它们都致力于让普通应用获得系统级权限,从而突破Android系统的限制。无论你是普通…

2026/10/21 3:32:25 阅读更多 →
CANN内测实战:从环境初始化到模型推理的完整指南

CANN内测实战:从环境初始化到模型推理的完整指南

前阵子看到某社区的“内测招募,免费体验CANN开发环境”活动,我第一时间就报名了。说实话,当时打动我的不只是“免费”两个字,而是想看看这个面向昇腾AI处理器的异构计算架构,在过去一年里到底进化到了什么程度。CANN这…

2026/10/21 3:32:25 阅读更多 →
Redis单线程还是多线程?从4.0到7.2的线程模型演进真相

Redis单线程还是多线程?从4.0到7.2的线程模型演进真相

1. 这个问题为什么值得花十分钟认真搞懂“Redis 到底是单线程还是多线程?”——这句提问在技术群、面试现场、甚至线上课程评论区里,几乎每周都会高频出现。它表面看是个“是非题”,但背后牵扯的是你对 Redis 性能本质、架构演进逻辑、以及高…

2026/10/21 3:31:24 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起:用户到底在追求什么“封号重开”这四个字,放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流,背后是大量的时间和精力成本。正常情况下,没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”,而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时,就意识到:单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →