You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将DraftJS带样式字符串转换为对应的HTML代码文本?

DraftJS 富文本转带样式HTML 实现方案

核心实现逻辑

  1. 解析DraftJS JSON字符串为可操作的JS对象,提前建立样式与HTML标签的映射表
  2. 对每个内容块的inlineStyleRanges按offset升序排序,确保样式处理顺序正确
  3. 把每个样式区间拆分为「插入开标签」和「插入闭标签」两个事件,按位置排序
  4. 遍历原文本的每个字符位置,先插入当前位置所有待插入的标签,再插入当前字符,最后拼接得到最终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, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;')
}

// 核心转换函数
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 09:39:02