如何将DraftJS带样式字符串转换为对应的HTML代码文本?
DraftJS 富文本转带样式HTML 实现方案
核心实现逻辑
- 解析DraftJS JSON字符串为可操作的JS对象,提前建立样式与HTML标签的映射表
- 对每个内容块的
inlineStyleRanges按offset升序排序,确保样式处理顺序正确 - 把每个样式区间拆分为「插入开标签」和「插入闭标签」两个事件,按位置排序
- 遍历原文本的每个字符位置,先插入当前位置所有待插入的标签,再插入当前字符,最后拼接得到最终HTML
标签映射规则参考
你可以根据需求自定义标签,常用映射如下:
- BOLD →
<strong>(开标签)、</strong>(闭标签) - UNDERLINE →
<u>、</u> - ITALIC →
<em>、</em>
完整可运行代码示例(JavaScript)
// 样式标签映射 const styleToTag = { BOLD: ['<strong>', '</strong>'], UNDERLINE: ['<u>', '</u>'], ITALIC: ['<em>', '</em>'] } // HTML特殊字符转义,避免XSS风险 const escapeHtml = (str) => { return str.replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/'/g, ''') } // 核心转换函数 const draftJsToHtml = (draftJsonStr) => { const draftData = JSON.parse(draftJsonStr) let htmlResult = '' // 遍历每个内容块 draftData.blocks.forEach(block => { const text = block.text const inlineStyles = block.inlineStyleRanges const insertEvents = [] // 生成标签插入事件 inlineStyles.forEach(styleRange => { const [openTag, closeTag] = styleToTag[styleRange.style] || [] if (!openTag) return // 跳过未配置的样式 const startPos = styleRange.offset const endPos = styleRange.offset + styleRange.length insertEvents.push({ pos: startPos, tag: openTag }) insertEvents.push({ pos: endPos, tag: closeTag }) }) // 事件按位置排序,相同位置的闭标签排在开标签前面,避免标签嵌套错误 insertEvents.sort((a, b) => { if (a.pos !== b.pos) return a.pos - b.pos // 闭标签以</开头,排在前面 return a.tag.startsWith('</') ? -1 : 1 }) let eventIndex = 0 let blockHtml = '' // 遍历文本字符,拼接标签和内容 for (let i = 0; i < text.length; i++) { // 插入当前位置所有标签 while (eventIndex < insertEvents.length && insertEvents[eventIndex].pos === i) { blockHtml += insertEvents[eventIndex].tag eventIndex++ } blockHtml += escapeHtml(text[i]) } // 插入文本末尾剩余的闭标签 while (eventIndex < insertEvents.length) { blockHtml += insertEvents[eventIndex].tag eventIndex++ } htmlResult += blockHtml }) return htmlResult } // 测试示例 const draftStr = `{ "blocks":[ {"key":"3uff", "text":"TextInBold TextInUnderLined TextInItalic", "type":"unstyled", "depth":0, "inlineStyleRanges":[ {"offset":0,"length":11,"style":"BOLD"}, {"offset":11,"length":17,"style":"UNDERLINE"}, {"offset":28,"length":12,"style":"ITALIC"}], "entityRanges":[], "data":{} }], "entityMap":{} }` console.log(draftJsToHtml(draftStr)) // 输出结果:<strong>TextInBold </strong><u>TextInUnderLined </u><em>TextInItalic</em>
注意事项
- 如果存在重叠样式,本逻辑会自动处理嵌套标签,符合HTML规范
- 如果需要处理块级样式(比如标题、列表),可以在遍历block的时候根据
type字段给整个块包裹对应块级标签 - 实体(链接、图片等)可以通过
entityRanges和entityMap做类似逻辑的扩展处理
内容的提问来源于stack exchange,提问作者Ashish Kamble
相关产品推荐
相关产品推荐

