MDX中直接写HTML标签会被当作文本而非可渲染元素,因解析器默认禁用原生HTML以保障安全;需通过自定义React组件、allowDangerousHtml配置或dangerouslySetInnerHTML(慎用)等方式实现HTML渲染。

MDX 里直接写 <div> 会被当成普通文本而不是 HTML
MDX 默认把未包裹的 HTML 标签当作文本节点处理,即使你写了 <button>Click</button>,它也不会渲染成可点击按钮,而是原样输出字符串。这是因为 MDX 的解析器(如 @mdx-js/mdx)默认禁用原生 HTML,防止 XSS 和保持内容安全。
- 只有显式启用
allowDangerousHtml: true(v2+)或skipExport: true(旧版)才可能生效,但不推荐 - 更稳妥的做法是用 React 组件封装 HTML 行为,比如写一个
<HtmlBlock>组件来包裹 - 如果你只是想加个样式容器,
<div className="note">...这类写法在 Next.js / Vite + MDX 环境中通常会报错,因为 className 不被识别 —— 得改用class属性(注意不是驼峰)
用 export const components 注册自定义 HTML 包装组件
这是最可控、也最符合 MDX 设计意图的方式:把 HTML 片段包装成 React 组件,在 MDX 文件顶部导出并注入渲染器。
- 在 MDX 文件开头写:
export const components = { html: ({ children, ...props }) => <div {...props}>{children}</div> } - 然后在正文中使用:
{`⚠️ 注意事项`} - 好处是支持 props 透传、能结合 Tailwind 或 CSS Modules、不会触发安全警告
- 缺点是不能直接写
<script>或内联事件(如onclick),React 会忽略它们
dangerouslySetInnerHTML 能跑但不该乱用
真要执行含 JS 的 HTML 片段(比如嵌入统计代码、第三方 widget),只能靠 React 的 dangerouslySetInnerHTML,但它必须出现在自定义组件内部,不能裸写在 MDX 正文里。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 新建一个
RawHtml.mdx组件,里面写:export default function RawHtml({ html }) { return <div dangerouslySetInnerHTML={{ __html: html }} />; } - 在目标 MDX 文件中导入并使用:
import RawHtml from './RawHtml.mdx' <RawHtml html={`<button onclick="alert(1)">test</button>`} /> - 注意:
html字符串必须是服务端可信来源,用户输入的内容绝对不能直接传入 - Next.js 13+ App Router 下,这个组件必须标记为
"use client",否则会报 hydration error
静态 HTML 导出时,<!--html--> 注释无效
有人试过用 HTML 注释绕过解析,比如写 <!--html--><iframe src="..."/>,但这只是注释掉内容,根本不会渲染。MDX 不识别这种伪指令。
立即学习“前端免费学习笔记(深入)”;
- MDX v2 没有类似 Jekyll 的
{% raw %}语法,别浪费时间找“开关” - 如果目标是生成静态站点(如 Docusaurus、Hugo + MDX),HTML 片段必须提前转成组件或通过插件预处理
- VitePress 用户要注意:它的 MDX 支持有限,
dangerouslySetInnerHTML在某些版本中会触发 warning,得配合vite-plugin-mdx配置白名单


















