如何在EJS网站中实现用户输入HTML的实时预览功能?
HTML实时预览功能修正方案
现有代码的核心问题
- 预览容器选错:用
<textarea>做预览区不行,它只能显示文本,没法渲染HTML结构,得换成<div>。 - ID大小写不匹配:HTML里的
id="longDesc"和id="liveDesc",JS里写成了小写的longdesc/livedesc,导致获取不到DOM元素。 - 重复绑定事件:每次按键触发
dis()都会新增一个keyup监听,会导致多次重复渲染,性能拉胯。 - 多余的Markdown解析:需求是支持HTML,不需要用
marked库,直接处理用户输入的HTML即可。 - 没必要的字符替换:用户输入的是原始HTML标签(比如
<h1>),不是转义后的<,替换操作反而会搞乱正常输入。
修正后的代码
HTML部分
<div class="form-group"> <label><i class="fad fa-texts"></i> Long Description<span style="color: rgb(175, 22, 22)">*</span> <p class="text-muted">(Html supported but markdown not supported)</p> </label> <textarea name="longDesc" id="longDesc" class="form-control" minlength="300" required="required" style="width: 100%; height: 300px;"></textarea> <!-- 把textarea换成div作为预览容器 --> <div name="liveDesc" id="liveDesc" class="form-control" style="width: 100%; height: 300px; overflow-y: auto; border: 1px solid #ced4da;"></div> </div>
JavaScript部分
// 页面加载完成后绑定一次事件即可 document.addEventListener('DOMContentLoaded', function() { const inputArea = document.getElementById('longDesc'); const previewArea = document.getElementById('liveDesc'); inputArea.addEventListener('input', function() { // 直接获取用户输入的HTML内容 let dirtyHtml = inputArea.value; // 用sanitizeHtml过滤不安全的标签(保持你的配置) const cleanHtml = sanitizeHtml(dirtyHtml, { allowedTags: sanitizeHtml.defaults.allowedTags.concat(['discord-message','discord-messages', 'img','iframe', 'style', 'h1', 'h2', 'link', 'mark', 'svg', 'span']), allowVulnerableTags: true, allowedAttributes: { '*': ["*"] } }); // 把过滤后的HTML渲染到预览区 previewArea.innerHTML = cleanHtml; }); });
关键修改说明
- 替换预览容器:用
<div>替代<textarea>,这样innerHTML设置的HTML才能被浏览器渲染成对应的样式。 - 统一ID大小写:确保JS里获取的ID和HTML里的完全一致。
- 单次事件绑定:在页面加载完成后只绑定一次
input事件(比keyup更全面,能覆盖粘贴、拖拽等输入场景),避免重复触发。 - 移除多余处理:删掉
marked解析和不必要的字符替换,直接处理用户输入的原始HTML。 - 保持安全过滤:保留
sanitizeHtml的配置,防止用户输入恶意HTML代码。
内容的提问来源于stack exchange,提问作者Ansh Tyagi
相关产品推荐
相关产品推荐

