跳到主內容
版本:3.5.2

MDX 和 React

Docusaurus內建支援MDX,這允許您在 Markdown 檔案中撰寫 JSX,並將其呈現為 React 組件。

查看MDX 文件,以了解您可以使用 MDX 做什麼有趣的事情。

偵錯 MDX

MDX 格式非常嚴格,而且可能會產生編譯錯誤。

使用MDX playground偵錯並確保您的語法有效。

資訊

最受歡迎的格式化程式,只支援舊版的 MDX v1。如果您收到意外的格式化結果,您可能想在有問題的區塊加入 {/* prettier-ignore */},或在 .prettierignore 中加入 *.mdx,直到 Prettier 適當地支援 MDX v3。 其中一位 MDX 的主要作者建議使用 remark-cli 搭配 remark-mdx

匯出元件

要在 MDX 檔案中定義自訂元件,您必須匯出它:只有以 export 開始的章節會被解析為元件,而不是散文。

export const Highlight = ({children, color}) => (
<span
style={{
backgroundColor: color,
borderRadius: '2px',
color: '#fff',
padding: '0.2rem',
}}>
{children}
</span>
);

<Highlight color="#25c2a0">Docusaurus green</Highlight> and <Highlight color="#1877F2">Facebook blue</Highlight> are my favorite colors.

I can write **Markdown** alongside my _JSX_!

注意它如何同時呈現 React 元件的標記和 Markdown 語法

https://127.0.0.1:3000
Docusaurus 綠色 Facebook 藍色 是我最喜歡的顏色。

我可以在 JSX 旁邊寫 Markdown

MDX 是 JSX

由於所有文件都是使用 MDX 進行解析,任何看起來像是 HTML 的東西實際上是 JSX。因此,如果您需要為元件設定內嵌樣式,請按照 JSX 的風格提供樣式物件。

/* Instead of this: */
<span style="background-color: red">Foo</span>
/* Use this: */
<span style={{backgroundColor: 'red'}}>Foo</span>

匯入元件

您也可以匯入在其他檔案中定義的自己的元件,或透過 npm 安裝的第三方元件。

<!-- Docusaurus theme component -->
import TOCInline from '@theme/TOCInline';
<!-- External component -->
import Button from '@mui/material/Button';
<!-- Custom component -->
import BrowserWindow from '@site/src/components/BrowserWindow';
提示

@site 別名指向您的網站目錄,通常是 docusaurus.config.js 檔案的位置。使用別名而不是相對路徑('../../src/components/BrowserWindow')可在變更檔案位置時或在版本化文件翻譯時,讓您不必更新導入路徑。

雖然在 Markdown 中宣告組件對於簡單的情況非常方便,但會因為編輯器支援度有限、發生解析錯誤的風險以及低可重複使用性而難以維護。當您的組件涉及複雜的 JS 邏輯時,請使用單獨的 .js 檔案

src/components/Highlight.js
import React from 'react';

export default function Highlight({children, color}) {
return (
<span
style={{
backgroundColor: color,
borderRadius: '2px',
color: '#fff',
padding: '0.2rem',
}}>
{children}
</span>
);
}
markdown-file.mdx
import Highlight from '@site/src/components/Highlight';

<Highlight color="#25c2a0">Docusaurus green</Highlight>
提示

如果您在許多檔案中使用相同的組件,則不必在每個地方都導入它——考慮將其新增到全域範圍。請參閱下方

MDX 組件範圍

除了導入組件匯出組件之外,在 MDX 中使用組件的第三個方式是將其註冊到全域範圍,這將使得它在每個 MDX 檔案中自動可見,而無需任何導入陳述式。

例如,假設有這個 MDX 檔案

- a
- list!

And some <Highlight>custom markup</Highlight>...

它將編譯成包含 ullipHighlight 元素的 React 組件。Highlight 不是一個原生 html 元素:您需要提供自己的 React 組件實作。

在 Docusaurus 中,MDX 組件範圍是由 @theme/MDXComponents 檔案提供的。它不是 React 組件本身,個人而言,與 @theme/ 別名下的其他大多數匯出不同:它是一份記錄,記錄著像是 Highlight 的標籤名稱,及其 React 組件實作。

如果您變動這個組件,您將找到所有已實作的標籤,您可以進一步變動各自的子組件來自訂我們的實作,例如 @theme/MDXComponents/Code(用於呈現Markdown 程式碼區塊)。

如果您想註冊額外的標籤名稱(例如上面的 <Highlight> 標籤),您應該考慮包裝 @theme/MDXComponents,這樣您就不必維護所有現有的對應關係。由於變動 CLI 尚未允許包裝非組件檔案,因此您應該手動建立包裝工具

src/theme/MDXComponents.js
import React from 'react';
// Import the original mapper
import MDXComponents from '@theme-original/MDXComponents';
import Highlight from '@site/src/components/Highlight';

export default {
// Re-use the default mapping
...MDXComponents,
// Map the "<Highlight>" tag to our Highlight component
// `Highlight` will receive all props that were passed to `<Highlight>` in MDX
Highlight,
};

現在,您可以在每個頁面自由地使用 <Highlight>,而不必寫入導入陳述式

I can conveniently use <Highlight color="#25c2a0">Docusaurus green</Highlight> everywhere!
https://127.0.0.1:3000

我在每個地方都能方便地使用 Docusaurus 綠色

警告

我們故意使用大寫標籤名稱,例如 Highlight

從 MDX v3+ 開始(Docusaurus v3+),小寫標籤名稱總是作為原生 HTML 元素呈現,並且不會使用您提供的任何組建對應。

警告

此功能是由 MDXProvider 提供支援。如果您在 React 頁面中匯入 Markdown,您必須透過 MDXContent 主題組件自行提供此提供者。

src/pages/index.js
import React from 'react';
import FeatureDisplay from './_featureDisplay.mdx';
import MDXContent from '@theme/MDXContent';

export default function LandingPage() {
return (
<div>
<MDXContent>
<FeatureDisplay />
</MDXContent>
</div>
);
}

如果您沒有使用 MDXContent 包覆匯入的 MDX,則無法使用全域範圍。

Markdown 和 JSX 互通性

Docusaurus v3 使用 MDX v3

MDX 語法大多與 CommonMark 相容,但由於您的 .mdx 檔案可以使用 JSX 並編譯成實際的 React 組件,因此更加嚴格(請檢視 遊樂場)。

有些有效的 CommonMark 功能無法在 MDX 中使用(更多資訊),特別是

  • 縮排程式碼區塊:改用三個反引號
  • 自動連結(<https://127.0.0.1:3000>):改用一般連結語法([https://127.0.0.1:3000](https://127.0.0.1:3000)
  • HTML 語法(<p style="color: red;">):改用 JSX(<p style={{color: 'red'}}>
  • 未跳脫的 {<:改用 \ 進行跳脫(\{\<
實驗性 CommonMark 支援

Docusaurus v3 讓您可以選擇採用不太嚴格、標準的 CommonMark 支援,並使用下列選項

  • format: md front matter
  • .md 檔案副檔名與 siteConfig.markdown.format: "detect" 組態結合使用

此功能為實驗性功能,目前有一些 限制事項

匯入程式碼片段

您不僅可以匯入包含元件定義的檔案,還可以將任何程式碼檔案作為原始文字匯入,然後將其插入程式碼區塊中,感謝 Webpack raw-loader。若要使用 raw-loader,您首先需要在專案中安裝它

npm install --save raw-loader

現在,您可以匯入其他檔案中的程式碼片段

myMarkdownFile.mdx
import CodeBlock from '@theme/CodeBlock';
import MyComponentSource from '!!raw-loader!./myComponent';

<CodeBlock language="jsx">{MyComponentSource}</CodeBlock>
https://127.0.0.1:3000
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React, {useState} from 'react';

export default function MyComponent() {
const [bool, setBool] = useState(false);
return (
<div>
<p>MyComponent rendered !</p>
<p>bool={bool ? 'true' : 'false'}</p>
<p>
<button onClick={() => setBool((b) => !b)}>toggle bool</button>
</p>
</div>
);
}

請參閱 JSX 中的程式碼區塊使用方式,瞭解 <CodeBlock> 元件的更多詳細資訊。

提示

您必須使用 <CodeBlock>,而不是 Markdown 三個反引號 ```,因為後者會將其任何內容原封不動地傳送出去,但您要在此插入匯入的文字。

警告

此功能仍處於實驗階段,且未來可能會有重大 API 變更。

匯入 Markdown

您可以使用 Markdown 檔案作為元件,並在其他地方匯入它們,無論是在 Markdown 檔案或 React 頁面中。

根據慣例,使用 **_ 檔案名稱字首** 不會建立任何文件頁面,表示 Markdown 檔案是 **「部份」**,供其他檔案匯入。

_markdown-partial-example.mdx
<span>Hello {props.name}</span>

This is text some content from `_markdown-partial-example.mdx`.
someOtherDoc.mdx
import PartialExample from './_markdown-partial-example.mdx';

<PartialExample name="Sebastien" />
https://127.0.0.1:3000
HelloSebastien

這是一些來自 _markdown-partial-example.md 內容的文字。

透過這種方式,您可以在多個頁面中重複使用內容,並避免複製素材。

可用匯出

在 MDX 頁面中,下列變數可用作全域變數

  • frontMatter:前置事項作為字串金鑰與數值記錄;
  • toc:目錄,作為標題樹狀結構。請參閱 內嵌目錄 了解更多具體使用案例。
  • contentTitle:Markdown 標題,為 Markdown 文字中的第一個 h1 標題。如果沒有標題(例如,在前置事項中指定標題),則為 undefined
import TOCInline from '@theme/TOCInline';
import CodeBlock from '@theme/CodeBlock';

The table of contents for this page, serialized:

<CodeBlock className="language-json">{JSON.stringify(toc, null, 2)}</CodeBlock>

The front matter of this page:

<ul>
{Object.entries(frontMatter).map(([key, value]) => <li key={key}><b>{key}</b>: {value}</li>)}
</ul>

<p>The title of this page is: <b>{contentTitle}</b></p>
https://127.0.0.1:3000

此頁面的目錄(已序列化)

[
{
"value": "Exporting components",
"id": "exporting-components",
"level": 3
},
{
"value": "Importing components",
"id": "importing-components",
"level": 3
},
{
"value": "MDX component scope",
"id": "mdx-component-scope",
"level": 3
},
{
"value": "Markdown and JSX interoperability",
"id": "markdown-and-jsx-interoperability",
"level": 3
},
{
"value": "Importing code snippets",
"id": "importing-code-snippets",
"level": 2
},
{
"value": "Importing Markdown",
"id": "importing-markdown",
"level": 2
},
{
"value": "Available exports",
"id": "available-exports",
"level": 2
}
]

此頁面的前置事項

  • id: react
  • description: 感謝 MDX,在 Docusaurus Markdown 文件中使用 React 的功能
  • slug: /markdown-features/react

此頁面的標題:MDX 和 React