Layui的textarea仅存储HTML字符串而非渲染富文本,清除标签需在提交前用正则函数stripHtml处理,注意空值判断、实体解码及laytpl模板中显式传入函数。
很多人误以为 textarea 里粘贴了带格式的内容,就等于“用了富文本”,其实不是。Layui 的 textarea 本身只是纯文本容器,它不会自动解析或渲染 HTML —— 你看到的 <p>hello</p> 就是字面量字符串,不是真实段落。所以“清除标签”本质是字符串处理,跟 DOM 渲染无关。
常见错误现象:直接对 textarea 调用 innerHTML = '' 或 val(''),结果清空的是整个内容,而不是只剥标签;或者在 laytpl 模板里写 {{ delhtml(d.content) }} 却忘了该函数没注入到模板作用域,导致报错 delhtml is not defined。
<div>、<span style="..."> 等标签,需清洗后存入数据库或展示textarea 的 change 事件里实时清洗 —— 用户还没输完就删标签,体验极差最轻量、兼容性最好、不依赖第三方库的方式就是正则。Layui 项目通常不引入 DOMPurify 或 he 这类包,所以直接写个函数最实在:
function stripHtml(str) {if (!str || typeof str !== 'string') return '';return str.replace(/]*>/g, '').replace(/s+/g, ' ').trim();}
说明:/]*>/g 匹配所有成对或单边标签(包括 <br>、<img src="">),s+ 是为了把标签删掉后残留的多个空格/换行压成一个空格,避免 “第一段 第二段” 变成 “第一段第二段”。
.replace(/<.>/g, '') —— . 会跨行匹配,在多行文本中可能吞掉大段内容 ),这个正则不管,得额外用 he.decode() 或手动替换str.replace(//gi, 'n').replace(//gi, 'n').replace(/]+>/g, '')分步处理
Layui 的 laytpl 不共享全局作用域,你在页面 script 里定义的 stripHtml 函数,默认进不了模板执行环境。必须显式传进去:
<script type="text/html" id="itemTpl">{{# var stripHtml = function(str){ return str ? str.replace(/<[^>]*>/g,'').replace(/s+/g,' ').trim() : ''; }}{{ stripHtml(d.desc) }}</script>
注意:模板里写的是 HTML 实体转义后的标签(< 和 >),否则浏览器会当成真实标签解析,导致模板加载失败。
laytpl(tpl).render(data, { stripHtml: window.stripHtml }) 注入d.desc 是空值或 undefined,str.replace 会报错,所以开头必须加 if (!str) 判断function(str) { ... } 最稳妥把清洗逻辑放在表单提交的 form.on('submit(filter)', ...) 回调里,能确保后端收到的就是干净文本,也避免前端反复清洗带来性能开销或状态不一致问题。
form.on('submit(demo)', function(data){data.field.desc = stripHtml(data.field.desc);// 后续 ajax 提交return false;});
这样做的好处是:用户看到的还是原始带标签内容(方便编辑),提交时才真正净化;万一后端需要原始 HTML 做审计或回溯,也能通过另一字段保留。
form.val() 赋值时就清洗 —— 如果用户改了又撤回,你已污染原始值layedit 富文本组件,那根本不是 textarea,而是 div + contenteditable,此时应调用 layedit.getContent(editIndex) 获取 HTML,再用上述正则清洗,而不是读 textarea.value
textarea 的粘贴行为有时会插入零宽空格(u200b),清洗后建议再加一句 .replace(/u200b/g, '')
实际用的时候,最常漏掉的是空值判断和实体转义处理——尤其当后端返回的数据里混着 <div> 这种二次编码内容,正则得先解码再删标签,否则白忙活。