当前位置: 首页 > news >正文

DOM 实战案例:无限滚动、懒加载与富文本安全

系列文章目录《JavaScript 基础与进阶笔记》前期偏基础巩固与常见面试点后续进入闭包、异步、工程化等进阶主题第 01 篇数据类型与类型判断第 02 篇变量声明与作用域第 03 篇闭包与高阶函数第 04 篇函数工厂第 05 篇this 指向与绑定第 06 篇原型与原型链第 07 篇类与继承第 08 篇JS 执行机制与异步队列第 09 篇数组常用方法第 10 篇字符串算法第 11 篇常见手写题合集上第 12 篇常见手写题合集下第 13 篇Promise 与 async/await第 14 篇数据结构基础第 15 篇垃圾回收与内存第 16 篇DOM 基础全面解析第 17 篇DOM 性能与渲染第 18 篇DOM 交互补充第 19 篇DOM 实战案例本文文章目录系列文章目录前言一、无限滚动IntersectionObserver 哨兵1.1 思路1.2 最小实现1.3 性能注意二、图片懒加载与预览2.1 懒加载2.2 点击预览事件委托三、拖拽排序HTML5 Drag and Drop 简版四、富文本渲染与安全4.1 安全 vs 不安全4.2 XSS 类型口述4.3 防御清单五、案例与前几篇对照六、易混淆点归纳七、思考与练习总结前言第 1618 篇已覆盖 DOM API、渲染性能与事件/可见性本篇用几个典型场景把知识串起来不求面面俱到。选取无限滚动IO 哨兵、图片懒加载与预览、简易拖拽排序、富文本渲染与安全。每个案例点出性能要点与常见坑超大数据量列表的虚拟滚动见第 12 篇XSS 体系化防御见系列后续安全专题。一、无限滚动IntersectionObserver 哨兵1.1 思路在列表底部放一个哨兵元素高度 1px 即可当其进入视口时请求下一页并追加 DOM加载完成后继续观察哨兵。[ 已渲染列表项 ... ] [ #sentinel 哨兵 ] ← 进入视口 → fetch 下一页1.2 最小实现constlistdocument.querySelector(#list);constsentineldocument.querySelector(#sentinel);letpage1;letloadingfalse;lethasMoretrue;constloadMoreasync(){if(loading||!hasMore)return;loadingtrue;try{constrowsawaitfetchPage(page);// 模拟接口if(rows.length0){hasMorefalse;observer.disconnect();return;}constfragdocument.createDocumentFragment();rows.forEach((text){constlidocument.createElement(li);li.textContenttext;frag.appendChild(li);});list.appendChild(frag);page;}finally{loadingfalse;}};constobservernewIntersectionObserver((entries){if(entries.some((e)e.isIntersecting))loadMore();},{rootMargin:200px});observer.observe(sentinel);asyncfunctionfetchPage(p){awaitnewPromise((r)setTimeout(r,300));returnp3?[p${p}-1,p${p}-2,p${p}-3]:[];}1.3 性能注意点说明防抖加载loading标志避免重复请求批量插入DocumentFragment减少回流第 17 篇数据极大改虚拟列表第 12 篇勿无限堆 DOM解绑无更多数据disconnect()路由离开unobserve二、图片懒加载与预览2.1 懒加载简单场景原生loadinglazy。imgsrcphoto.jpgloadinglazyalt描述/需提前加载距离、或统一 IO 管理与第 18 篇一致constionewIntersectionObserver((entries,obs){entries.forEach((entry){if(!entry.isIntersecting)return;constimgentry.target;img.srcimg.dataset.src;img.removeAttribute(data-src);obs.unobserve(img);});},{rootMargin:100px});document.querySelectorAll(img[data-src]).forEach((img)io.observe(img));占位建议固定宽高或 aspect-ratio避免加载后CLS布局偏移。2.2 点击预览事件委托相册缩略图用委托绑在容器上点击后把大图塞进模态层constgallerydocument.querySelector(#gallery);constmodaldocument.querySelector(#preview);constbigmodal.querySelector(img);gallery.addEventListener(click,(e){constthumbe.target.closest(img[data-full]);if(!thumb)return;big.srcthumb.dataset.full;big.altthumb.alt;modal.hiddenfalse;});modal.addEventListener(click,(){modal.hiddentrue;big.removeAttribute(src);// 可选释放大图});安全data-full应来自可信 CDN 地址勿把用户输入直接当 URL用户上传图需服务端校验。三、拖拽排序HTML5 Drag and Drop 简版适合有序列表重排移动端常改用手势库此处展示桌面端最小思路。ulidsortablelidraggabletrueA/lilidraggabletrueB/lilidraggabletrueC/li/ulconstuldocument.querySelector(#sortable);letdragElnull;ul.addEventListener(dragstart,(e){constlie.target.closest(li);if(!li)return;dragElli;e.dataTransfer.effectAllowedmove;});ul.addEventListener(dragover,(e){e.preventDefault();// 允许 dropconstlie.target.closest(li);if(!li||lidragEl)return;constrectli.getBoundingClientRect();constaftere.clientYrect.toprect.height/2;ul.insertBefore(dragEl,after?li.nextSibling:li);});ul.addEventListener(dragend,(){dragElnull;// 可把 ul 内顺序同步到后端});注意dragover里preventDefault必须否则无法 drop。频繁insertBefore会触发回流项不多时可接受项多考虑只记录索引、drop 时再 DOM 一次。自定义拖拽样式可用setDragImage动画优先transform第 17 篇。四、富文本渲染与安全评论、文章详情常需渲染HTML 富文本。核心原则永远不要把不可信字符串直接innerHTML进页面。4.1 安全 vs 不安全// ❌ 用户输入含 script 或 onerror → XSSbox.innerHTMLuserComment;// ✅ 纯文本展示box.textContentuserComment;// ✅ 必须渲染 HTML白名单净化后再插入box.innerHTMLDOMPurify.sanitize(userComment);4.2 XSS 类型口述类型来源例存储型服务端存了恶意 HTML评论区持久化脚本反射型URL 参数回显到页?qscript...DOM 型前端把不可信数据写进 DOMinnerHTML location.hash4.3 防御清单输出转义默认textContent必须 HTML 时用DOMPurify等白名单库。CSPContent-Security-Policy限制脚本来源后续安全篇展开。Cookie敏感 Token 设HttpOnly降低被脚本读走风险。富文本编辑器提交前服务端再次净化前端净化不能替代后端。// 简易 HTML 转义无标签场景constescapeHtml(s)s.replace(//g,amp;).replace(//g,lt;).replace(//g,gt;).replace(//g,quot;);面试聚焦富文本 白名单净化 服务端校验innerHTML userInput是典型反例。五、案例与前几篇对照案例用到的前序知识无限滚动第 18 篇 IO第 17 篇 Fragment第 12 篇虚拟列表升级懒加载/预览第 18 篇 IO /loadinglazy第 18 篇事件委托拖拽排序第 16 篇 DOM 增删第 17 篇回流富文本第 16 篇textContentvsinnerHTML六、易混淆点归纳无限滚动 ≠ 虚拟列表前者可不断 append数据量大必须虚拟化。IO 哨兵记得loading锁与disconnect。预览模态大图 URL 须可信防javascript: 伪协议等。拖拽在 touch 端体验差移动场景另选方案。前端 DOMPurify不能代替后端过滤。七、思考与练习1.无限滚动列表越来越长滚动变卡优先怎么优化解析上虚拟列表第 12 篇控制 DOM 数量而非一味加页。2.评论接口返回 HTML前端如何渲染解析DOMPurify.sanitize后再innerHTML服务端仍须白名单过滤。3.相册 100 张图每个缩略图单独click监听好吗解析不好容器事件委托closest(img)第 18 篇。4.拖拽排序时为何dragover要preventDefault解析默认不允许 drop不阻止则drop不触发。5.哨兵刚进视口就连续触发两次加载可能原因解析未加loading锁或未在请求期间unobserve哨兵。总结无限滚动底部IO 哨兵 分页请求 Fragment追加数据量大改虚拟列表。图片简单loadinglazy要控距用IO预览用委托 模态。拖拽HTML5 DnD 最小实现注意回流与移动端差异。富文本禁裸innerHTML净化 服务端防 XSS。DOM 阶段至此完结。下一篇进入CSS 布局居中、BFC、Flex/Grid 等。
http://www.gsyq.cn/news/1398887.html

相关文章:

  • 2026工业大风扇厂家推荐:工业吊扇生产厂家+大吊扇厂家推荐名录 - 栗子测评
  • 告别双系统安装焦虑:保姆级图解ThinkPad Win10+Ubuntu分区与引导修复全流程
  • 终极指南:如何在香橙派AIPRO上部署DeepSeek-R1-Distill-Qwen-7B量化模型
  • 2026蒸发冷省电空调厂家推荐:车间通风降温公司+车间降温设备厂家推荐精选 - 栗子测评
  • CANN/ops-nn HardShrink算子
  • 三步搞定iPhone抢购难题:Apple Store预约助手实战指南
  • 别再只调PID了!深入浅出聊聊IMU姿态解算中的‘互补滤波’思想
  • 城市规划师必备:如何用ArcGIS插件高效评估区域风环境(迎风面密度保姆级教程)
  • 2026年附近的装修公司/绵阳全包装修公司/绵阳老房改造装修公司本地热门榜 - 品牌宣传支持者
  • ResourcesSaverExt:如何一键批量下载网页资源并保持原始目录结构
  • 如何用LSPosed构建模块化Android Hook框架:从理解到实战
  • 从TRPO到PPO:OpenAI如何用‘Clipping’技巧让强化学习训练更稳定?
  • 从Demo跑通到项目实战:海康工业相机(HIK)在Visual Studio中的完整开发流程拆解
  • 别再只做目标检测了!试试用YOLOv8和CLIP给你的检测结果打上语义标签
  • 锌铝合金产品定制哪家好?2026锌合金零配件压铸/铝合金零配件压铸厂家推荐 - 栗子测评
  • InsForge API网关完整指南:如何配置请求转发与智能速率限制
  • ArabianGPT-0.3B-QA vs 传统问答模型:为什么3亿参数模型能实现更高效率?
  • 为什么83%的制造企业AI Agent项目卡在POC阶段?一线交付总监吐露3个未公开的失败根因
  • 一文读懂GGUF格式:Agent-STAR-RL-7B-i1量化模型的存储与加载原理
  • CANN算子注册表访问器库
  • 认知无线电入门:不懂复杂公式?用能量检测法快速理解频谱感知核心
  • ICode竞赛Python一级通关秘籍:用变量控制飞船和角色,保姆级代码逐题解析
  • 从Velodyne到图像:手把手教你用Python解析KITTI点云与图像数据(附代码)
  • Qwen2.5-0.5B-Instruct完全指南:如何在华为昇腾NPU上部署轻量级AI模型
  • 用Python和Keras从零搭建CNN:我的胃病影像识别课程设计复盘(附完整代码与数据集)
  • 保姆级教程:用Python和OpenCV玩转AprilTag二维码检测(附完整代码)
  • 终极PDF工具箱:7步掌握PDF补丁丁的完整使用指南
  • VMware给Kali扩容后开机慢?别慌,八成是swap的UUID没改对(附详细排查步骤)
  • InsForge漏洞防护:如何有效防范SQL注入与XSS攻击的完整指南 [特殊字符]️
  • 数字IC面试必考:Radix-4 Booth乘法器原理、Verilog实现与优化要点