MDX 和 React
Docusaurus內建支援MDX,這允許您在 Markdown 檔案中撰寫 JSX,並將其呈現為 React 組件。
查看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 語法
我可以在 JSX 旁邊寫 Markdown!
由於所有文件都是使用 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';
雖然在 Markdown 中宣告組件對於簡單的情況非常方便,但會因為編輯器支援度有限、發生解析錯誤的風險以及低可重複使用性而難以維護。當您的組件涉及複雜的 JS 邏輯時,請使用單獨的 .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>
);
}
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>...
它將編譯成包含 ul
、li
、p
和 Highlight
元素的 React 組件。Highlight
不是一個原生 html 元素:您需要提供自己的 React 組件實作。
在 Docusaurus 中,MDX 組件範圍是由 @theme/MDXComponents
檔案提供的。它不是 React 組件本身,個人而言,與 @theme/
別名下的其他大多數匯出不同:它是一份記錄,記錄著像是 Highlight
的標籤名稱,及其 React 組件實作。
如果您變動這個組件,您將找到所有已實作的標籤,您可以進一步變動各自的子組件來自訂我們的實作,例如 @theme/MDXComponents/Code
(用於呈現Markdown 程式碼區塊)。
如果您想註冊額外的標籤名稱(例如上面的 <Highlight>
標籤),您應該考慮包裝 @theme/MDXComponents
,這樣您就不必維護所有現有的對應關係。由於變動 CLI 尚未允許包裝非組件檔案,因此您應該手動建立包裝工具
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!
我在每個地方都能方便地使用 Docusaurus 綠色!
我們故意使用大寫標籤名稱,例如 Highlight
。
從 MDX v3+ 開始(Docusaurus v3+),小寫標籤名稱總是作為原生 HTML 元素呈現,並且不會使用您提供的任何組建對應。
此功能是由 MDXProvider
提供支援。如果您在 React 頁面中匯入 Markdown,您必須透過 MDXContent
主題組件自行提供此提供者。
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'}}>
) - 未跳脫的
{
和<
:改用\
進行跳脫(\{
和\<
)
Docusaurus v3 讓您可以選擇採用不太嚴格、標準的 CommonMark 支援,並使用下列選項
format: md
front matter.md
檔案副檔名與siteConfig.markdown.format: "detect"
組態結合使用
此功能為實驗性功能,目前有一些 限制事項。
匯入程式碼片段
您不僅可以匯入包含元件定義的檔案,還可以將任何程式碼檔案作為原始文字匯入,然後將其插入程式碼區塊中,感謝 Webpack raw-loader。若要使用 raw-loader
,您首先需要在專案中安裝它
- npm
- Yarn
- pnpm
npm install --save raw-loader
yarn add raw-loader
pnpm add raw-loader
現在,您可以匯入其他檔案中的程式碼片段
import CodeBlock from '@theme/CodeBlock';
import MyComponentSource from '!!raw-loader!./myComponent';
<CodeBlock language="jsx">{MyComponentSource}</CodeBlock>
/**
* 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 檔案是 **「部份」**,供其他檔案匯入。
<span>Hello {props.name}</span>
This is text some content from `_markdown-partial-example.mdx`.
import PartialExample from './_markdown-partial-example.mdx';
<PartialExample name="Sebastien" />
這是一些來自 _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>
此頁面的目錄(已序列化)
[
{
"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