ol不可直接编辑,需用JavaScript控制:为每个li内嵌contenteditable的span,配合CSS计数器实现自动编号,提交前手动提取结构化数据并过滤XSS。

ol本身不能直接编辑,得靠JavaScript接管内容
ol 是语义化容器,不是输入控件。浏览器不会让它像 input 或 textarea 那样双击就改文字——你看到的“可编辑”效果,全是 JS 动态监听、替换 DOM 实现的。
常见错误是给 ol 加 contenteditable="true":它确实能点进去打字,但会破坏结构——li 可能被拆成多个文本节点,编号错乱,li 之间还能插入换行或格式标签,后续用 JS 提取步骤时根本没法 parse。
- 正确做法是每个
li内部包一层span或div,只让这个内层contenteditable="true" - 用
blur或keydown.enter触发保存,避免用户输一半就跳走 - 别忘了过滤空格和纯空白行:
li.textContent.trim() === ""就该自动移除该项
动态增删步骤必须同步更新编号逻辑
原生 start 属性只在初始渲染时生效,JS 插入新 li 后,编号不会自动重排。比如你有个 ,再用 appendChild 加一个 li,它会显示为 “3”,而不是 “4”。
真正可控的方式是放弃依赖 HTML 属性,改用 CSS 计数器:
ol { counter-reset: step; }
ol li { counter-increment: step; }
ol li::before { content: counter(step) ". "; }
- 这样新增/删除
li后,浏览器自动重算所有::before的值 - 若需从第 5 步开始,写
counter-reset: step 4;(注意是起始值减 1) - 别在 JS 中手动改
li.textContent = "5. xxx",否则 CSS 计数器失效,且语义丢失
提交前要把步骤转成结构化数据,不能只读 innerHTML
表单提交时,ol 不会自动成为请求参数。你必须在 submit 事件里手动提取每步内容,拼成数组或 JSON 发送到后端。
错误示例:new FormData(form) 拿不到 ol 里的文字——它不是表单控件。
- 安全提取方式:
Array.from(ol.querySelectorAll("li > span[contenteditable]")).map(el => el.textContent.trim()) - 要防 XSS:如果后端要渲染这些步骤,前端提交前应做基础过滤(如移除
<script></script>、onerror等) - 若步骤含子操作(如“2.1 安装依赖”),建议用
data-level="2.1"存结构信息,比纯文本解析更可靠
移动端长按编辑容易误触,得加防抖和视觉反馈
在 iOS 或安卓上,contenteditable 元素长按会弹系统菜单,遮挡编辑框;手指稍一滑动就可能触发滚动,导致光标丢失。
实操要点:
- 给可编辑区域加
user-select: text,禁用-webkit-user-select: none类样式 - 点击
li时,先聚焦内部span,再用getSelection().collapse()把光标移到末尾 - 连续两次点击同一项才进入编辑态,避免单击就激活(可用
click+ 时间戳判断) - 编辑中加背景色或边框高亮,让用户明确当前焦点在哪一步
最易被忽略的是:没处理软键盘弹出后页面滚动偏移,导致编辑框被遮住。得监听 focusin 后调用 el.scrollIntoView({ block: "nearest" })。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











