
mdx-js/vue 完全指南在 Vue 项目中用 Context 为 MDX 注入组件【免费下载链接】mdxMarkdown for the component era项目地址: https://gitcode.com/gh_mirrors/md/mdxmdx-js/vue是 MDX 官方生态中面向 Vue 的 context 组件提供器它基于 Vue 的provide/inject机制让嵌套的 MDX 文件无需层层手动传递components属性即可共享自定义组件映射。读完本文你将掌握mdx-js/vue的安装方式、MDXProvider与useMDXComponents两个核心 API 的用法、providerImportSource编译选项的底层实现原理以及如何在 Vue 3 项目中正确配置并验证这套组件注入体系。什么是 mdx-js/vuemdx-js/vue是一个基于context上下文的组件提供器作用是把 Vue 与 MDX 结合起来。它对外只提供两个标识符MDXProviderVue 组件和useMDXComponents组合式函数且没有默认导出——这一点在 packages/vue/test/index.js 的公开 API 测试中有明确验证assert.deepEqual(Object.keys(await import(mdx-js/vue)).sort(), [ MDXProvider, useMDXComponents ])整个包的实际实现非常精简核心代码全部位于 packages/vue/lib/index.js对外入口 packages/vue/index.js 仅做了一行再导出export {MDXProvider, useMDXComponents} from ./lib/index.js什么时候需要它为什么官方说不是必需官方文档给出的第一条重要提示是这个包并不是 MDX 在 Vue 中运行的必要条件。单层使用时直接给 MDX 组件传components属性即可完成组件替换引入 Provider 只会徒增包体。但在嵌套 MDX 文件在 MDX 中再 import 其他 MDX/Markdown 文件的场景下手动透传会变得繁琐——你不得不在每个子组件上写License components{props.components} /这样的重复代码。针对这一痛点使用 MDX 指南中给出了三步设置方案根据所用框架安装mdx-js/react、mdx-js/preact或mdx-js/vue在 MDX 编译器的ProcessorOptions中把providerImportSource配置为对应包名Vue 场景即mdx-js/vue从该包导入MDXProvider用它包裹最顶层的 MDX 内容组件并传入components。Context 的职责正如官方文档所述提供一种在组件树中传递数据、而无需在每一层手动透传 props 的方式。这正是MDXProvider存在的价值。安装mdx-js/vue是ESM only的包不支持 CommonJS。根据 packages/vue/package.json 的声明当前版本为3.1.1type: moduleexports: ./index.jspeerDependencies要求vue 3.0.0依赖的是 Vue 3 的组合式 API 与 Fragment 渲染运行时依赖仅types/mdx ^2.0.0用于提供MDXComponents类型并标记sideEffects: false方便打包器摇树优化。Node.js版本 16配合 npm 安装npm install mdx-js/vue在 Deno 中使用 esm.shimport {MDXProvider} from https://esm.sh/mdx-js/vue3在浏览器中直接以模块方式使用 esm.shscript typemodule import {MDXProvider} from https://esm.sh/mdx-js/vue3?bundle /script?bundle参数用于让 esm.sh 返回一个适合浏览器直接执行的打包产物。基本使用下面是一个完整的 Vue 3 使用示例摘自官方文档假设你通过mdx-js/esbuild、mdx-js/loader、mdx-js/node-loader或mdx-js/rollup等集成工具把./post.mdx编译为 JS并且编译配置中设置了options.providerImportSource: mdx-js/vue。import {MDXProvider} from mdx-js/vue import {createApp} from vue import Post from ./post.mdx // ^-- 假设已用某个集成工具将 MDX 编译为 JS且配置了 // options.providerImportSource: mdx-js/vue createApp({ data() { return {components: {h1: h2}} }, template: MDXProvider v-bind:componentscomponentsPost //MDXProvider, components: {MDXProvider, Post} })注意v-bind:componentscomponentscomponents数据在data()中定义MDX 编译产物中的# Hello world会在渲染时通过 Provider 上下文找到h1的替代组件最终被渲染成h2。官方特别提醒你完全可以不用MDXProvider直接把components作为属性传给 MDX 组件。对于单个 MDX 文件更简洁的等价写法是-createApp({ - data() { - return {components: {h1: h2}} - }, - template: MDXProvider v-bind:componentscomponentsPost //MDXProvider, - components: {MDXProvider, Post} -}) createApp(Post, {components: {h1: h2}})如何开始使用 MDX 与 Vue可参考入门指南Provider 的完整设计动机与适用场景可参考使用 MDX 指南中的 MDX provider 章节。API 详解本包导出MDXProvider和useMDXComponents两个标识符没有默认导出。MDXProvider(properties?)MDX 上下文的提供器类型为 Vue 的Component。它接收一个可选的components属性MDXComponents类型并在渲染时把传入的组件通过 Vue 的provide注入到整棵子树中。useMDXComponents(components?)从 MDX Context 中读取当前组件映射。参数没有参数文档标题中的(components?)仅为历史遗留写法源码签名useMDXComponents()不接受任何入参返回值当前的组件映射类型为MDXComponents该类型来自mdx/types.js由types/mdx提供。PropsMDXProvider的 TypeScript 配置类型包含一个字段字段类型说明componentsMDXComponents可选需要注入的额外组件工作原理provide/inject 与 providerImportSource从源码层面看MDXProvider的实现极简见 packages/vue/lib/index.jsimport {Fragment, createVNode, inject, provide} from vue export const MDXProvider { name: MDXProvider, props: { components: { default() { return {} }, type: Object } }, setup(properties) { provide($mdxComponents, properties.components) }, render() { return createVNode( Fragment, undefined, this.$slots.default ? this.$slots.default() : [] ) } } export function useMDXComponents() { return inject($mdxComponents, {}) }几个值得注意的实现细节上下文键setup中用provide($mdxComponents, ...)注入useMDXComponents用inject($mdxComponents, {})读取默认值为空对象保证未提供 Provider 时也能安全运行。透传渲染render()返回一个Fragment包裹的默认插槽内容因此MDXProvider本身不产生多余 DOM 节点可以任意包裹 MDX 内容组件。懒读取useMDXComponents只有在被调用时才从上下文中取值这为 MDX 编译产物的运行时按需注入组件提供了钩子。编译侧的配合机制位于 packages/mdx/lib/plugin/recma-jsx-rewrite.js。当providerImportSource被设置时该插件会在编译产物中以useMDXComponents为导入名、_provideComponents为本地别名从providerImportSource指向的模块插入 import 语句对应源码中createImportProvider函数在_createMdxContent函数内调用_provideComponents()获取上下文中的组件再与props.components及局部定义组件做合并对应parameters.push({... _provideComponents ...})及后续的ObjectExpression合并逻辑合并结果赋给_components并从中解构出 MDX 中实际用到的组件名如const {MyComponent, wrapper: MDXLayout} _components。也就是说providerImportSource的值本身是什么并不重要关键是该模块必须导出一个名为useMDXComponents的标识符——编译插件只认这个名字。mdx-js/vue恰好满足这一约定因此可以直接作为该选项的值。如果不想走编译期注入也可以使用mdx-js/mdx的evaluate在运行时编译并执行 MDX配置providerImportSource: #并在run的 options 中传入useMDXComponents见 packages/mdx/lib/util/resolve-evaluate-options.js。需要说明的是run/runSync内部通过new Function求值执行编译产物见 packages/mdx/lib/run.js官方明确标注了这会 eval JavaScript的风险警示因此只应运行可信内容。测试验证packages/vue/test/index.js 用 Node 内置的node:test框架对本包做了全面覆盖核心断言包括公开 API 仅导出MDXProvider与useMDXComponents两个标识符通过compilerun评估 MDX# hi→h1hi/h1验证 MDX 内容本身能被 Vue 正确渲染支持在 MDX 内定义 Vue 组件export const A {render() {...}}后以A /使用支持直接传components{components: {h1: h2}}渲染出h2hi/h2支持MDXProvider包裹含带components、不带components、无插槽内容三种形态无内容时渲染为空字符串。测试通过vue/server-renderer的renderToString得到 HTML 字符串后去除 SSR 注释再做断言说明该包同时适用于客户端渲染与服务端渲染场景。TypeScript 类型支持mdx-js/vue完全使用 TypeScript 编写类型并额外导出Props类型。要获得完整类型提示需要确保 TypeScript 的JSX命名空间已正确配置——通常通过安装并引入框架自身的类型Vue 场景即vue包自带类型来完成。编译期providerImportSource的类型校验与MDXComponents的定义由types/mdx提供这也是该包唯一的运行时依赖。兼容性unified 社区维护的项目遵循与仍在维护的 Node.js 版本保持兼容的策略每发布一个 major 版本就会放弃对已停止维护的 Node 版本的支持。因此当前发布线mdx-js/vue^3的目标是兼容Node.js 16并保持 ESM only 的模块形态。安装或升级前请确认你的运行时满足上述前提。安全说明关于 MDX 内容与组件注入的安全边界官方在安全章节中有统一说明。结合本包的实际行为需要特别记住MDX 支持嵌入 JSX 表达式和组件配合run/runSync这类求值机制时只应编译和执行可信来源的内容否则可能带来任意代码执行风险。许可证mdx-js/vue以 MIT 协议发布版权归 Compositor 与 Vercel 所有。【免费下载链接】mdxMarkdown for the component era项目地址: https://gitcode.com/gh_mirrors/md/mdx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考