摘要
昨天我修了一个按钮问题:页面上的“查看进度”不能点。表面看是按钮坏了,实际根因在模板安全上。
模板把结构化参数直接塞进 HTML 事件属性里,里面的引号把浏览器解析截断了。函数没有拿到完整参数,按钮自然也就没反应。
这篇文章讲的是为什么“只是拼一下字符串”在前端模板里经常不是小事。
目录
- 按钮不能点时不要只看按钮
- 模板拼接为什么危险
- 结构化数据应该怎么进页面
- 为什么要补回归验证
- 长期收益
- FAQ
按钮不能点时不要只看按钮
用户看到的是按钮不能点击,我一开始也会先检查前端事件有没有绑定。
但这类问题不能只看 JS 函数。按钮本身是模板渲染出来的,如果模板生成的 HTML 已经坏了,后面的函数再正确也没用。
这次就是这样。页面里看起来有点击事件,但浏览器实际解析出来的属性已经被截断。
所以排查前端问题时,我会看三层:模板输出、浏览器实际 DOM、运行时函数。
模板拼接为什么危险
模板最容易让人放松警惕。
有时候只是把一个对象转成 JSON,再放进 onclick 里。看起来很自然。但 JSON 里有引号,HTML 属性也有引号,两者如果没有正确转义,就会互相打断。
这类 bug 很隐蔽,因为源码里看起来像是对的,浏览器里却已经变形。
尤其是按钮参数里有标题、路径、状态、时间等可变内容时,更不能随便拼。
结构化数据应该怎么进页面
我的原则是:结构化数据进入 HTML 时,必须认真处理转义。
如果放在属性里,就要使用适合属性上下文的转义。如果数据复杂,最好不要塞进 inline onclick,而是放到 data 属性或脚本数据块里,再由 JS 读取。
这样可以减少引号冲突,也让行为和数据分离。
并不是说 inline 事件永远不能用,而是只要参数复杂,就要格外小心。
为什么要补回归验证
这类 bug 修起来不难,但容易复发。
以后有人改模板,可能又把 JSON 放回双引号属性里。所以我会补一个能覆盖关键渲染结果的测试,至少确认生成的调用不会被截断。
测试不是为了证明这次修好了,而是为了防止下次又坏。
长期收益
一个进度按钮不能点,会让用户怀疑整个任务系统。
但背后可能只是一个转义细节。这就是前端模板的特点:小错误会放大成大体验问题。
长期看,把模板安全当成基础规范,可以让很多按钮、弹窗和任务入口更可靠。
FAQ
为什么源码看起来对,页面还是坏?
因为浏览器解析 HTML 时会处理引号和属性边界。源码字符串正确,不代表最终 DOM 正确。
JSON 能不能放进 onclick?
简单参数可以,复杂参数不建议。要放也必须使用正确转义。
这种问题怎么验证?
看浏览器实际 DOM,再触发点击。必要时加模板渲染测试,确认事件参数完整。