本文介绍了 MDX 格式是什么。它展示了如何在 MDX 中使用 Markdown、JSX、JavaScript 表达式以及 ESM 中的导入和导出语句。有关如何将MDX集成到您的项目中的详细信息,请参阅入门文档。

先决条件

要编写和享受MDX,您应该熟悉Markdown(查看此速查表和教程以获取帮助)和JavaScript(特别是JSX)。

适用于组件时代的Markdown

MDX允许您在markdown内容中使用JSX。您可以导入组件,例如交互式图表或警报,并嵌入到您的内容中。这使得使用组件编写长篇内容变得轻松愉快。🚀

更实际地说,MDX可以解释为将markdown与JSX结合的格式,如下所示:

MDX

  1. # 你好,世界!
  2. <div className="note">
  3. > 一些引人注目的事情在一个块引用中!
  4. </div>

标题和块引用是markdown,而那些HTML样式的标签是JSX。对于常见的强调或标题等事物,Markdown通常更自然,更容易输入。JSX是JavaScript的扩展,看起来_像HTML,但使用组件(可重用的内容)非常方便。

这个示例在<div>上使用了className。那是因为它是为React编写的,React期望类是这样定义的。其他框架,例如Vue和Preact,期望类的定义方式有所不同,因此请注意,根据使用的工具,JSX的编写方式有所不同。

MDX还支持JavaScript的其他一些特性:大括号内的表达式({1 + 1})和ESM(importexport)。

MDX语法

注意:您不必使用@mdx-js/*包与此语法。或始终使用它。如果使用捆绑器集成,可以通过文件扩展名(.mdx.md)在MDX和markdown之间进行切换。另外,可以使用options.format

MDX语法将markdown与JSX结合在一起。这给了我们一种类似于文学编程的东西。它还给了我们两种语言的奇怪组合:markdown是敏感于空白宽容的(您键入的内容可能不完全正确,但不会崩溃),而JavaScript是不敏感于空白严格的(它对打字错误会崩溃)。

奇怪的是,我们相当喜欢它们如何结合在一起!

Markdown

与HTML或JSX相比,Markdown通常在常见事物的强调或标题等方面更自然,更简洁。与下面的HTML相比,它看起来更像是预期的内容。

HTML

  1. <blockquote>
  2. <p>带有<em>一些</em>强调的引用。</p>
  3. </blockquote>

您可以用markdown(或MDX)写出等效的内容,如下所示:

Markdown

  1. > 带有*一些*强调的引用。

MDX默认支持标准的markdown(CommonMark):

Markdown

  1. # 标题(1级)
  2. ## 标题2
  3. ### 3
  4. #### 4
  5. ##### 5
  6. ###### 6
  7. > 引用块
  8. * 无序
  9. * 列表
  10. 1. 有序
  11. 2. 列表
  12. 一个段落,介绍主题性断点:
  13. ---
  14. ```js
  15. some.code()

一个链接,一个图片,一些强调,一些加粗,最后是一点code()

  1. 非标准的markdown功能(如GFMfrontmatter、数学、语法突出显示)可以通过插件启用(请参阅[¶使用插件](../extending-mdx/#using-plugins))。
  2. 有些markdown功能在MDX中不起作用:
  3. * 缩进的代码在MDX中不起作用:
  4. MDX
  5. ```mdx
  6. console.log(1) // 这是MDX中的段落!
  1. 这样做的原因是为了使您可以很好地缩进组件:
  2. MDX
  3. ```mdx
  4. <main>
  5. <article>
  6. # 你好!
  7. </article>
  8. </main>
  9. ```
  • 自动链接在MDX中不起作用。原因是它们可能与JSX不可区分(例如:),我们更喜欢明确指定。如果您想要链接,请使用完整链接:[描述性文本](https://and-the-link-here.com)
  • HTML语法在MDX中不起作用,因为它被JSX替换(<img>变为<img />)。您可以在大括号中使用JavaScript注释来代替HTML注释:{/* 注释! */}
  • 未转义的左尖括号/小于号(<)和左花括号({)必须转义:\<\{(或使用表达式:{'<'}{'{'}

有关MDX与markdown的区别的更多信息,请参阅此处的文档

JSX

JSX是JavaScript的扩展,看起来像HTML,但使用组件(可重用的内容)非常方便。JSX通常与前端框架(如React、Preact或Vue)一起使用。这些框架增加了对组件的支持,使您可以更改重复的内容,如下面的标记:

HTML

  1. <h2>你好,金星!</h2>
  2. <h2>你好,火星!</h2>

…到JSX(或MDX)如下:

MDX

  1. <Welcome name="Venus" />
  2. <Welcome name="Mars" />

JSX适用于组件。它使重复的事物更加清晰,并允许关注点的分离。MDX支持JSX语法。以下内容看起来很像HTML:

MDX

  1. <h1>标题!</h1>
  2. <abbr title="超文本标记语言">HTML</abbr> 是一种可爱的语言。
  3. <section>
  4. 这里是*markdown*在**JSX**中的呈现方式!
  5. </section>

但正如之前提到的,您也可以使用组件。请注意,组件必须被定义。您可以导入它们,本地定义它们,或稍后传递它们(参见§使用MDX):

MDX

  1. <MyComponent id="123" />
  2. 您还可以使用包含组件的对象,例如`myComponents`对象上的`thisOne`组件:<myComponents.thisOne />
  3. <Component
  4. open
  5. x={1}
  6. label={'这是一个字符串,*不是* markdown!'}
  7. icon={<Icon />}
  8. />

MDX 与 JSX 不同的特殊情况

表达式

MDX还支持大括号内的JavaScript表达式:

MDX

  1. 两个 🍰 是:{Math.PI * 2}

表达式可以包含完整的JavaScript程序,只要它们是(包裹在)一个可以渲染的表达式。您可以这样使用IIFE

MDX

  1. {(function () {
  2. const guess = Math.random()
  3. if (guess > 0.66) {
  4. return <span style={{color: 'tomato'}}>看我们。</span>
  5. }
  6. if (guess > 0.33) {
  7. return <span style={{color: 'violet'}}>谁能猜到?!</span>
  8. }
  9. return <span style={{color: 'goldenrod'}}>不是我。</span>
  10. })()}

表达式可以为空,或者只包含一个注释:

MDX

  1. {/* 一个注释! */}

ESM

MDX还支持JavaScript中的importexport语句。这些ESM功能也可以在MDX中使用来定义事物:

MDX

  1. import {External} from './some/place.js'
  2. export const Local = properties => <span style={{color: 'red'}} {...properties} />
  3. 一个 <External>外部</External> 组件和一个 <Local>本地</Local>。

ESM也可以用于非组件(数据):

MDX

  1. import {Chart} from './chart.js'
  2. import population from './population.js'
  3. export const pi = 3.14
  4. <Chart data={population} label={'一些内容和 ' + pi} />

插入

如果文本和标签在同一行上,您可以在JSX中使用markdown“内联”,但不能使用“块”:

MDX

  1. <div># 这不是标题,但 *这* 是强调</div>

文本和标签在同一行上不会生成块,因此也不会生成<p>

MDX

  1. <div>
  2. 这是一个 `p`。
  3. </div>

我们根据此规则(同一行或不同行)区分。不是基于HTML元素的语义。因此,您可以构建不正确的HTML(您不应该):

MDX

  1. <h1 className="main">
  2. 不要这样做:这是一个 `p` 在一个 `h1` 中
  3. </h1>
  4. <h1 className="main">这样做:一个 `h1` 和 `code`</h1>

如果文本和标签在同一行上,但相应的标签在不同行上,则无法包装“块”:

MDX

  1. 欢迎! <a href="about.html">
  2. 这是...
  3. # 猎鹰!</a>

这是因为为了解析markdown,我们首先必须将其分成“块”。所以在这种情况下有两个段落和一个标题。在第一个段落中留下一个开放的a标签,在标题中留下一个零散的关闭a标签。

进一步阅读