ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

现代 JavaScript 教程实战:用事件委托捕获容器内链接导航,确认用户是否离开

现代 JavaScript 教程实战:用事件委托捕获容器内链接导航,确认用户是否离开 文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载导读本文围绕《现代 JavaScript 教程》zh.javascript.info中「浏览器默认行为」章节的一个经典练习展开让某个容器idcontents内所有链接在点击时先弹出确认框询问用户是否真的要离开用户拒绝则阻止浏览器跳转。文章完整继承题目要求与官方解答并深入剖析事件委托event delegation、closest(a)、getAttribute(href)、confirm()与return false的组合用法帮助你在动态渲染的页面上实现离开确认这类拦截式交互。读完本文你将掌握一套可直接复用的容器内链接点击拦截实战模板以及return false在onevent与addEventListener下的本质区别。任务需求回顾在 2-catch-link-navigation 的题目中要求实现这样一个功能使所有包含idcontents的元素内的链接询问用户是否真的要离开。如果用户不想离开那就不离开。题目还给出了两个关键细节约束它们是决定解题方案的核心元素内的 HTML 可以被随时动态加载或重新生成因此无法在加载时找到所有链接并逐个添加处理程序——必须使用事件委托。内容中可能有嵌套的标签链接中也是例如a href..i.../i/a因此不能简单地判断event.target是否恰好是一个a元素。初始页面结构见 source.view/index.html容器中包含两个链接a hrefhttps://wikipedia.orgWikipedia/a和带嵌套i标签的a hrefhttps://w3.orgiW3.org/i/a。为什么必须使用事件委托题目中的第一条细节决定了方案的走向。若页面内容是静态的理论上可以直接遍历所有a并逐个绑定click处理程序但这里的内容可能由 Ajax、模板引擎或用户操作动态生成、随时替换。此时逐一绑定的做法会带来两个问题新插入的链接不会自动获得处理程序除非每次内容变化后重新绑定容易遗漏且难以维护处理程序与 DOM 生命周期耦合删除节点时还可能造成内存泄漏隐患。事件委托的思路完全不同把click监听器绑定在稳定的祖先容器这里是#contents上利用事件冒泡机制捕获所有后代链接的点击再在事件发生时通过 DOM API 判断点击目标。由于监听器只绑定一次后续无论容器内 HTML 如何重排、增删拦截逻辑始终生效。这一模式正是 浏览器默认行为章节 中菜单示例所用技巧的进阶版——菜单示例用event.target.nodeName ! A判断而本任务还需要处理嵌套标签的情况。完整解决方案官方解答位于 solution.md可直接运行的成品见 solution.view/index.html。核心脚本如下script contents.onclick function(event) { function handleLink(href) { let isLeaving confirm(Leave for ${href}?); if (!isLeaving) return false; } let target event.target.closest(a); if (target contents.contains(target)) { return handleLink(target.getAttribute(href)); } }; /script下面逐行拆解这段代码的四个关键设计。1. 用closest(a)处理嵌套标签event.target是事件真正发生的元素。当用户点击a hrefhttps://w3.orgiW3.org/i/a中的i时event.target是i而不是a。此时若沿用菜单示例中的event.target.nodeName ! A判断就会漏掉这个链接。event.target.closest(a)会从目标元素开始向上冒泡查找最近的a祖先若点击的是a本身返回该a若点击的是a内部的i同样返回外层的a若点击的是容器内与链接无关的文本或元素则返回null。这一行同时解决了链接内有嵌套标签与点击非链接区域两个问题正是题目第二条细节的答案。2. 用contents.contains(target)做双保险由于监听器挂在#contents上理论上触发的事件都来自容器内部。那为什么还要contents.contains(target)检查考虑closest(a)返回的祖先链closest会一直向上查找直到document根节点。如果容器内部嵌套了一个覆盖更大区域的链接例如某个链接的display撑满了容器closest可能返回容器之外的祖先a。contents.contains(target)确保最终处理的一定是容器内的链接避免误拦截容器外的导航。同时这种显式检查也提高了代码的可读性与健壮性便于后续把处理函数抽离复用。3. 用getAttribute(href)而不是link.href官方解答特别强调最好使用link.getAttribute(href)来代替link.href。二者的区别在于link.href是 DOM 属性property浏览器会把它解析为基于当前页面地址的完整绝对 URLlink.getAttribute(href)返回 HTML 属性attribute中的原始字符串与源码中书写的内容一致。对离开确认场景而言向用户展示原始链接地址更符合直觉同时如果页面通过base标签或脚本动态修改了基础地址原始值也能避免误导。这一细节体现了 property 与 attribute 的差异是题目在工程层面的隐藏考点。4. 用confirmreturn false阻止默认导航handleLink中调用confirm(\Leave for ${href}?)弹出一个确认对话框用户点取消时返回false该返回值最终由contents.onclick 处理程序返回给浏览器从而阻止点击链接后的默认跳转行为。这里必须强调return false生效的前提条件只有通过onevent方式如onclick属性或element.onclick ...分配的处理程序其return false才会被浏览器识别为阻止默认行为。本任务使用contents.onclick function(event) {...}正是onevent赋值因此返回false有效。如果改用addEventListener(click, ...)注册返回false会被忽略必须显式调用event.preventDefault()。这一规则在 浏览器默认行为章节 中有专门警告return true无任何意义事件处理程序的返回值在其他情况下一律被忽略。!-- 两种等效写法onclick 属性中均可 -- a href/ onclickreturn false不跳转/a a href/ onclickevent.preventDefault()不跳转/a一个常见的坑为什么return false会失效仓库中紧邻本任务的练习 1-why-return-false-fails 专门演示了这个陷阱a hrefhttps://w3.org onclickhandler()the browser will go to w3.org/a script function handler() { alert(...); return false; // 期望阻止跳转但实际不会 } /script原因在于浏览器解析onclickhandler()时实际生成的匿名处理函数是function(event) { handler() }——handler()的返回值没有被使用因此return false起不到任何作用。修复方法有两种!-- 方式一显式把返回值交给浏览器 -- a hrefhttps://w3.org onclickreturn handler()w3.org/a !-- 方式二改用 event.preventDefault() -- script function handler(event) { alert(...); event.preventDefault(); } /script a hrefhttps://w3.org onclickhandler(event)w3.org/a这个练习与本任务形成对照本任务中contents.onclick function(event) { ... return handleLink(...); }的返回值是直接来自处理函数本身的所以能正确生效而通过属性内嵌函数调用时需要手动return一次。理解了这一点就彻底掌握了return false的生效边界。延伸从离开确认到生产环境方案官方解答的 solution.md 提示了该模式的现实意义在真实产品中我们往往不是弹confirm而是向服务器发送一条 logging 请求记录访客从哪个链接离开或者用 Ajax 加载内容并就地展示若业务允许。这属于阻止默认行为后用 JavaScript 接管的典型场景与 浏览器默认行为章节 中介绍的event.preventDefault()、return false、event.defaultPrevented、passive选项等机制一脉相承需要多个层级的处理程序协作如按钮级与文档级上下文菜单同时存在时可用event.defaultPrevented判断事件是否已被内层处理避免stopPropagation()切断其他监听者的信息获取移动端滚动类事件如touchmove可用addEventListener的passive: true声明不阻止默认行为换取滚动流畅度。同时应牢记章节末尾的语义警告不要滥用阻止默认行为。a应当保持导航的语义保留用户右键在新窗口打开、搜索引擎索引链接等原生能力拦截导航只应用于真正需要确认或劫持的场景且需给出合理的替代交互。总结本任务展示了一个高价值的实战组合拳四个要点缺一不可设计点作用对应代码事件委托应对动态生成/替换的 HTML只绑定一次监听contents.onclick ...closest(a)穿透嵌套标签如ai.../i/a找到真实链接event.target.closest(a)contains(target)防止误拦截容器之外的祖先链接contents.contains(target)confirmreturn false询问用户并阻止默认导航if (!isLeaving) return false;对照官方实现 solution.view/index.html 与初始页面 source.view/index.html 可直观看到未拦截与已拦截的效果差异。掌握这套模式后你可以轻易扩展出站内站外链接区分提示表单未保存离开警告下载链接计数上报等一系列基于拦截导航的交互同时保持代码对动态内容的健壮性。赞分享文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载相关推荐JavaScript 教程实战用事件委托拦截元素内链接导航catch link navigationJavaScript 教程实战用事件委托拦截元素内链接导航catch link navigation 导读 本篇文章基于 Modern JavaScrip文档/教程前端现代 JavaScript 教程事件冒泡、捕获与事件委托一文讲清 JavaScript 事件机制现代 JavaScript 教程事件冒泡、捕获与事件委托一文讲清 JavaScript 事件机制 《现代 JavaScript 教程》The Modern文档教程前端拦截链接导航Modern JavaScript Tutorial 中事件委托与 preventDefault 的实战解析拦截链接导航Modern JavaScript Tutorial 中事件委托与 preventDefault 的实战解析 本篇指南聚焦 Modern Java文档/教程前端上一篇刘海屏菜单栏图标遮挡用 Ice 快速找回清爽的 Mac 菜单栏下一篇TensorFlow Models 的 research/rebar 指南用 REBAR 实现离散隐变量模型的低方差无偏梯度估计创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表