Mdx 让 Markdown 步入组件时代

前言

MDX 试图让书写 Markdown 和 JSX 更简单、更具 表现力。当你将组件 (甚至可以是动态的或需要加载数据的组件)与 Markdown 混合书写时,你将写出更有趣的内容。

创新互联主营陵川网站建设的网络公司,主营网站建设方案,成都App制作,陵川h5重庆小程序开发搭建,陵川网站营销推广欢迎陵川等地区企业咨询

MDX 是什么

MDX 是一种书写格式,允许你在 Markdown 文档中无缝地插入 JSX 代码。你还可以导入(import)组件,例如交互式图表或弹框,并将它们 嵌入到内容当中。

前提条件

您应该熟悉 markdown 语法和 JavaScript 语法 (特别是 JSX)。

MDX 示例比如官网的一个例子,如下代码

import {Chart} from './snowfall.js'
export const year = 2018

# Last year’s snowfall

In {year}, the snowfall was above average.
It was followed by a warm spring which caused
flood conditions in many of the nearby rivers.


展示效果

效果.png

如何使用

在 create-react-app 中 只需要安装 @mdx-js/loader, create-react-app 5 支持自定义 loader

src/App.jsx

/* eslint-disable import/no-webpack-loader-syntax */
import Content from "!@mdx-js/loader!./content.mdx";

export default function App() {
return ;
}

src/content.mdx

# Hello, world!

This is **markdown** with JSX: MDX!

如果是 webpack 项目只需要加一个 @mdx-js/loader就可以支持

module.exports = {
module: {
// …
rules: [
// …
{
test: /\.mdx?$/,
use: [
// `babel-loader` is optional:
{ loader: "babel-loader", options: {} },
{
loader: "@mdx-js/loader",
/** @type {import('@mdx-js/loader').Options} */
options: {
/* jsxImportSource: …, otherOptions… */
},
},
],
},
],
},
};

插件支持

MDX 也支持插件配置,也就是原先的 markdown 插件

比如要让 markdown 支持表格和 checkboxList ,可以使用 remark-gfm 插件;

比如要让 markdown 支持数学公式 可以使用 rehype-katex 插件;

在 option 中可以传入参数,代码如下:

import rehypeKatex from 'rehype-katex'
import remarkMath from 'remark-math'


module.exports = {
module: {
// …
rules: [
// …
{
test: /\.mdx?$/,
use: [
// `babel-loader` is optional:
{loader: 'babel-loader', options: {}},
{
loader: '@mdx-js/loader',
/** @type {import('@mdx-js/loader').Options} */
options: {remarkPlugins: [remarkGfm], rehypePlugins: [rehypeKatex]}}
}
]
}
]
}
}

当然也可以支持自定义插件,比如 img 要加上默认样式,限制其最大宽度,href 跳转要改成新窗口打开等 ,如何写 markdown 插件可以查看 unifiedjs.com

定义组件

在支持了 mdx 之后, 可以给 mdx 定义组件, 比如给 H1 传递默认样式等,或者加入默认组件,例如 https://beta.reactjs.org/ 就加入了很多自定义组件,代码示例如下:

import React from "react";
import ReactDom from "react-dom";
import Post from "./post.mdx"; // Assumes an integration is used

export const H1 = ({ className, ...props }: HeadingProps) => (
className={cn(className, "text-5xl font-bold leading-tight")}
{...props}
/>
);

const components = {
h1: H1,
};

ReactDom.render(
,
document.querySelector("#root")
);

MDX provider

每个文档都要传 components 很麻烦?我们可以在最外层导入 MDXProvider

import React from 'react'
import ReactDom from 'react-dom'
import Post from './post.mdx' // Assumes an integration is used to compile MDX -> JS.
import {Heading, /* … */ Table} from './components/index.js'
+import {MDXProvider} from '@mdx-js/react'

const components = {
h1: Heading.H1,
// …
table: Table
}

ReactDom.render(
- ,
+
+
+
,
document.querySelector('#root')
)

在线运行

以上实例都是在构建时运行,那么能让 MDX 在浏览器运行呢,比如未来,博客的编辑器支持 MDX, 那么我们的博客文章页面就可以有更多交互了。

比如数据通过服务端返回,下面代码是 next.js 示例

import { useState, useEffect, Fragment } from "react";
import * as runtime from "react/jsx-runtime.js";
import { compile, run } from "@mdx-js/mdx";

export default function Page({ code }) {
const [mdxModule, setMdxModule] = useState();
const Content = mdxModule ? mdxModule.default : Fragment;

useEffect(() => {
(async () => {
setMdxModule(await run(code, runtime));
})();
}, [code]);

return ;
}

export async function getStaticProps() {
const code = String(
await compile("# hi", { outputFormat: "function-body" /* …otherOptions */ })
);
return { props: { code } };
}

实时运行

例如:官方的 palyground,就可以实时运行,左边写代码,右侧展示文档

官方 playground

最简单的代码如下:

import { VFile } from "vfile";
import { evaluate, } from "@mdx-js/mdx";

const value='## header'

const file = new VFile({ basename: "example.mdx", value });

const {default:Result}=await evaluate(file, runtime);

这个 Result 就是一个react 组件,如要实现类似功能可以参考官方 github 中的 editor.client.js。

小结

Markdown 所有程序员都爱,Markdown 在标准化、结构化、组件化都存在硬伤,有了 MDX ,Markdown 有了富交互、内容形态的编写,希望 MDX 尽早、尽快、更多的投入到的互联网产品中,也希望 MDX 的解析也来越标准化。

文章标题:Mdx 让 Markdown 步入组件时代
本文来源:http://www.hantingmc.com/qtweb/news40/527240.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联