4300 字
22 分钟
MDX 在 Astro 中的高级应用
MDX 在 Astro 中的高级应用
一、MDX 基础概念
1.1 什么是 MDX?
MDX(Markdown + JSX)是一种将 Markdown 与 JSX 结合的格式,允许你在 Markdown 文档中直接使用 React/Vue/Astro 组件。
// 基础示例import { Chart } from '../components/Chart.jsx';
# 我的数据分析报告
这是一个包含交互式图表的文档。
<Chart data={[10, 20, 30, 40, 50]} title="销售增长趋势"/>1.2 为什么在 Astro 中使用 MDX?
| 优势 | 描述 |
|---|---|
| 内容创作友好 | 内容团队可以使用熟悉的 Markdown |
| 交互性增强 | 在静态内容中嵌入动态组件 |
| 组件复用 | 重用现有的 Vue/React/Angular 组件 |
| 类型安全 | 配合 TypeScript 获得更好的开发体验 |
二、Astro 中 MDX 的配置与集成
2.1 基础配置
import { defineConfig } from 'astro/config';import mdx from '@astrojs/mdx';import vue from '@astrojs/vue';
export default defineConfig({ integrations: [ mdx({ // MDX 配置选项 shikiConfig: { theme: 'github-dark', }, }), vue(), // 支持在 MDX 中使用 Vue 组件 ], markdown: { // 支持 GFM(GitHub Flavored Markdown) gfm: true, // 智能标点 smartypants: true, },});2.2 安装依赖
# 安装 MDX 支持npm install @astrojs/mdx
# 安装 Vue 支持(如果需要在 MDX 中使用 Vue 组件)npm install @astrojs/vue vue
# 可选:安装语法高亮主题npm install shiki2.3 MDX 组件配置
import { defineCollection, z } from 'astro:content';import { docsSchema } from '@astrojs/starlight/schema';
// 定义 MDX 集合const mdxCollection = defineCollection({ type: 'content', schema: ({ image }) => z.object({ title: z.string(), description: z.string(), publishDate: z.date(), updatedDate: z.date().optional(), author: z.string(), tags: z.array(z.string()), // 支持图片 coverImage: image().optional(), // 自定义元数据 difficulty: z.enum(['beginner', 'intermediate', 'advanced']).optional(), interactive: z.boolean().default(false), }),});
export const collections = { 'mdx-content': mdxCollection,};三、在 MDX 中使用 Vue 交互组件
3.1 基础 Vue 组件集成
---import Counter from '../../components/vue/Counter.vue';import DataVisualizer from '../../components/vue/DataVisualizer.vue';import QuizComponent from '../../components/vue/Quiz.vue';
title: 'MDX 中的 Vue 交互组件演示'description: '学习如何在 MDX 中集成 Vue 交互式组件'publishDate: '2023-10-15'tags: ['mdx', 'vue', 'interactive']interactive: true---
# Vue + MDX 交互式文档
## 1. 基础计数器组件
下面是一个 Vue 计数器组件,完全在 MDX 中工作:
<Counter initialValue={10} step={2} client:load/>
**代码说明:**- `client:load` 属性确保组件在页面加载时激活- 可以传递 props 给 Vue 组件- 组件完全交互式,状态在客户端维护
## 2. 数据可视化组件
<DataVisualizer data={[ { month: 'Jan', value: 4000 }, { month: 'Feb', value: 3000 }, { month: 'Mar', value: 5000 }, { month: 'Apr', value: 8000 }, ]} type="bar" client:visible/>
## 3. 交互式测验组件
<QuizComponent questions={[ { question: '什么是 MDX?', options: [ '一种新的编程语言', 'Markdown 和 JSX 的结合', '一个 CSS 框架', '一个数据库' ], correctAnswer: 1 } ]} client:idle/>3.2 Vue 组件开发规范
<template> <div class="mdx-counter" :class="{ interactive: isInteractive }"> <div class="counter-display"> <h3>{{ title }}</h3> <div class="count">{{ count }}</div> </div>
<div class="controls"> <button @click="decrement" :disabled="count <= min"> − </button> <button @click="reset"> 重置 </button> <button @click="increment" :disabled="count >= max"> + </button> </div>
<div v-if="showStats" class="stats"> <p>历史最高: {{ maxCount }}</p> <p>点击次数: {{ clickCount }}</p> </div> </div></template>
<script setup>import { ref, computed, onMounted } from 'vue';
const props = defineProps({ initialValue: { type: Number, default: 0 }, min: { type: Number, default: -Infinity }, max: { type: Number, default: Infinity }, title: { type: String, default: '计数器' }, showStats: { type: Boolean, default: true }, step: { type: Number, default: 1 }});
// 响应式状态const count = ref(props.initialValue);const maxCount = ref(props.initialValue);const clickCount = ref(0);const isInteractive = ref(true);
// 计算属性const countStyle = computed(() => ({ color: count.value > 0 ? 'green' : count.value < 0 ? 'red' : 'gray', fontSize: `${Math.min(2, 1 + Math.abs(count.value) * 0.1)}rem`}));
// 方法const increment = () => { if (count.value < props.max) { count.value += props.step; updateStats(); }};
const decrement = () => { if (count.value > props.min) { count.value -= props.step; updateStats(); }};
const reset = () => { count.value = props.initialValue; clickCount.value += 1;};
const updateStats = () => { clickCount.value += 1; if (count.value > maxCount.value) { maxCount.value = count.value; }};
// 生命周期onMounted(() => { console.log('MDX Counter mounted in Astro');});
// 暴露方法供父组件调用defineExpose({ increment, decrement, reset, getCount: () => count.value});</script>
<style scoped>.mdx-counter { border: 2px solid #e5e7eb; border-radius: 12px; padding: 1.5rem; margin: 2rem 0; background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%); transition: all 0.3s ease;}
.mdx-counter.interactive:hover { border-color: #3b82f6; box-shadow: 0 10px 25px -5px rgba(59, 130, 246, 0.1);}
.counter-display { text-align: center; margin-bottom: 1.5rem;}
.counter-display h3 { margin: 0 0 0.5rem 0; color: #374151; font-size: 1.25rem;}
.count { font-size: 3rem; font-weight: bold; transition: all 0.3s ease;}
.controls { display: flex; gap: 1rem; justify-content: center; margin-bottom: 1.5rem;}
.controls button { padding: 0.5rem 1rem; border: none; border-radius: 6px; background: #3b82f6; color: white; font-size: 1rem; cursor: pointer; transition: all 0.2s ease;}
.controls button:hover:not(:disabled) { background: #2563eb; transform: translateY(-2px);}
.controls button:disabled { background: #9ca3af; cursor: not-allowed;}
.stats { border-top: 1px solid #e5e7eb; padding-top: 1rem; font-size: 0.875rem; color: #6b7280;}</style>3.3 复杂的交互式文档示例
---import LineChart from '../../components/vue/charts/LineChart.vue';import BarChart from '../../components/vue/charts/BarChart.vue';import PieChart from '../../components/vue/charts/PieChart.vue';import DataControls from '../../components/vue/DataControls.vue';import CodeEditor from '../../components/vue/CodeEditor.vue';
title: '数据可视化教程'description: '交互式学习数据可视化'publishDate: '2023-11-20'tags: ['tutorial', 'data-viz', 'interactive']difficulty: 'intermediate'interactive: true---
# 交互式数据可视化教程
## 介绍
本教程通过实际操作来学习数据可视化。你可以:
1. 📊 直接与图表交互2. 🔧 修改数据和配置3. 💾 查看实时代码变化
---
## 第一部分:基础图表
### 1. 折线图
<LineChart client:load id="line-chart-1" title="月度销售数据" :data="[ { month: '1月', sales: 4000 }, { month: '2月', sales: 3000 }, { month: '3月', sales: 5000 }, { month: '4月', sales: 8000 }, { month: '5月', sales: 7000 }, { month: '6月', sales: 9000 }, ]" :config="{ showGrid: true, animate: true, curve: 'smooth' }"/>
**练习:** 尝试修改上方的数据,观察图表变化。
### 2. 柱状图
<BarChart client:visible id="bar-chart-1" title="产品类别销售" :data="[ { category: '电子产品', sales: 12000 }, { category: '服装', sales: 8500 }, { category: '食品', sales: 9500 }, { category: '书籍', sales: 4500 }, ]" :colors="['#3b82f6', '#10b981', '#f59e0b', '#ef4444']"/>
---
## 第二部分:动态数据控制
<DataControls client:load v-slot="{ data, updateData }"> <div class="data-section"> <h3>实时数据控制面板</h3>
<div class="chart-container"> <PieChart :data="data" title="动态饼图" /> </div>
<div class="controls"> <p>当前数据点数量: {{ data.length }}</p> <button @click="updateData('add')">添加数据点</button> <button @click="updateData('remove')">移除数据点</button> <button @click="updateData('randomize')">随机化数据</button> </div> </div></DataControls>
---
## 第三部分:代码编辑器集成
### 实时代码演示
<CodeEditor client:idle language="javascript" :initial-code="`// 数据可视化配置示例const config = { type: 'line', data: { labels: ['Jan', 'Feb', 'Mar', 'Apr'], datasets: [{ label: 'Sales', data: [65, 59, 80, 81], borderColor: 'rgb(75, 192, 192)', tension: 0.1 }] }, options: { responsive: true, plugins: { legend: { position: 'top', } } }};
// 创建图表const ctx = document.getElementById('myChart').getContext('2d');const myChart = new Chart(ctx, config); `" :theme="'github-dark'" height="400px"/>
**练习:** 修改上面的代码,然后点击"运行"查看结果。
---
## 总结
通过这个交互式教程,你学到了:
1. 如何在 MDX 中集成 Vue 图表组件2. 如何创建动态交互的数据可视化3. 如何让读者直接参与学习过程
<QuizComponent client:load :questions="[ { question: '在 Astro MDX 中使用 Vue 组件需要什么配置?', options: [ '什么都不需要,默认支持', '安装 @astrojs/vue 并添加到配置', '只能使用 React 组件', '需要特殊的构建配置' ], correctAnswer: 1, explanation: '需要在 astro.config.mjs 中添加 vue() 集成' } ]"/>四、高级 MDX 功能与模式
4.1 自定义 MDX 组件映射
import Alert from './Alert.astro';import Card from './Card.astro';import Tabs from './Tabs.astro';import TabItem from './TabItem.astro';
// 自定义组件映射export const components = { Alert, // 将 Markdown 的 > 警告转换为 Alert 组件 Card, // 自定义卡片组件 Tabs, // 标签页组件 TabItem, // 标签页项 // 覆盖默认的 HTML 元素 h1: (props) => <h1 className="text-4xl font-bold" {...props} />, a: (props) => <a className="text-blue-600 hover:underline" {...props} />, // Vue 组件也可以映射 VueCounter: () => import('../vue/Counter.vue').then(m => m.default),};// mdx.d.ts - TypeScript 类型定义declare module '*.mdx' { import { AstroComponentFactory } from 'astro/dist/runtime/server';
export const frontmatter: Record<string, any>; export const file: string; export const url: string;
const Component: AstroComponentFactory; export default Component;}4.2 MDX 布局与包装器
---import type { Props } from 'astro';import TableOfContents from '../components/TableOfContents.astro';import AuthorBio from '../components/AuthorBio.astro';import ShareButtons from '../components/vue/ShareButtons.vue';import ReadingProgress from '../components/vue/ReadingProgress.vue';import MdxComponents from '../components/mdx/CustomComponents';
const { frontmatter, headings } = Astro.props;---
<html lang="zh-CN"><head> <title>{frontmatter.title}</title> <meta name="description" content={frontmatter.description} /></head><body> <!-- 阅读进度条 --> <ReadingProgress client:load />
<div class="mdx-container"> <!-- 侧边栏目录 --> <aside class="sidebar"> <TableOfContents headings={headings} /> </aside>
<!-- 主内容区域 --> <main class="content"> <article> <header> <h1>{frontmatter.title}</h1> <div class="meta"> <span>发布日期: {frontmatter.publishDate.toLocaleDateString()}</span> <span>作者: {frontmatter.author}</span> </div> </header>
<!-- MDX 内容渲染 --> <div class="mdx-content"> <slot /> </div>
<!-- 分享按钮 --> <ShareButtons client:load :title="frontmatter.title" :url={Astro.url} />
<!-- 作者简介 --> <AuthorBio author={frontmatter.author} /> </article> </main> </div>
<style> .mdx-container { display: grid; grid-template-columns: 280px 1fr; gap: 3rem; max-width: 1200px; margin: 0 auto; padding: 2rem; }
.mdx-content { line-height: 1.8; }
.mdx-content :global(h2) { margin-top: 3rem; padding-bottom: 0.5rem; border-bottom: 2px solid #e5e7eb; }
.mdx-content :global(pre) { border-radius: 8px; padding: 1rem; overflow-x: auto; } </style></body></html>4.3 动态导入与懒加载
---import { Suspense } from 'vue';
title: '动态组件加载演示'description: '展示如何在 MDX 中懒加载大型组件'---
# 动态组件加载
## 大型组件的懒加载
为了避免页面初始加载过重,我们可以动态导入大型组件:
```jsxconst HeavyComponent = React.lazy(() => import('../components/HeavyComponent'));在 Vue 中:
条件性加载
根据用户交互动态加载组件:
### 4.4 MDX 与状态管理
```mdx---// src/content/tutorials/state-management.mdximport { createStore } from '../../stores/mdxStore';import CounterDisplay from '../../components/vue/CounterDisplay.vue';import ControlsPanel from '../../components/vue/ControlsPanel.vue';import HistoryViewer from '../../components/vue/HistoryViewer.vue';
title: 'MDX 中的状态管理'description: '学习在 MDX 文档中管理组件状态'---
# 跨组件状态管理
## 问题场景
在复杂的交互式文档中,多个组件可能需要共享状态。例如:
- 多个图表显示相同的数据集- 控制面板影响多个展示组件- 用户输入需要在不同地方同步
## 解决方案:共享状态存储
### 1. 创建共享存储
```javascript// stores/mdxStore.jsimport { reactive } from 'vue';
export const store = reactive({ // 共享数据 data: [], // 共享配置 config: { theme: 'light', animation: true, }, // 共享方法 updateData(newData) { this.data = newData; }, toggleTheme() { this.config.theme = this.config.theme === 'light' ? 'dark' : 'light'; }});2. 在组件中使用
---
## 五、最佳实践与性能优化
### 5.1 性能优化策略
#### 组件懒加载配置
```javascript// astro.config.mjsimport { defineConfig } from 'astro/config';import mdx from '@astrojs/mdx';
export default defineConfig({ integrations: [ mdx({ optimize: { // 自动拆分大型 MDX 文件 split: true, // 预加载关键组件 prefetch: { threshold: 0.5, // 视口 50% 时预加载 }, }, }), ],});图片优化
---import { Image } from 'astro:assets';import heroImage from '../../assets/hero.jpg';
title: '图片优化示例'---
# 使用优化图片
<!-- 自动优化的图片 --><Image src={heroImage} alt="示例图片" widths={[400, 800, 1200]} sizes="(max-width: 768px) 100vw, 50vw" formats={['avif', 'webp', 'jpg']} loading="lazy"/>
<!-- 背景图片优化 --><div style={{ backgroundImage: `url(${heroImage.src})`, backgroundSize: 'cover', backgroundPosition: 'center', height: '400px', }}> 背景图片内容</div>5.2 可访问性最佳实践
---// 可访问的交互式组件示例import AccessibleChart from '../../components/vue/AccessibleChart.vue';import KeyboardNavigable from '../../components/vue/KeyboardNavigable.vue';
title: '可访问的 MDX 内容'---
# 可访问性指南
## 1. 键盘导航支持
<KeyboardNavigable client:load role="region" aria-label="交互式数据面板" tabindex="0"> 这个组件完全支持键盘导航: - Tab 键导航 - 回车键激活 - 箭头键选择</KeyboardNavigable>
## 2. 屏幕阅读器友好的图表
<AccessibleChart client:load :data="chartData" :aria-label="'销售数据图表,显示季度增长'" :describe-by="'chart-description'"/>
<div id="chart-description" class="sr-only"> 此图表显示 2023 年四个季度的销售数据。 第一季度:100万,第二季度:150万, 第三季度:180万,第四季度:220万。 呈稳定增长趋势。</div>
<style>.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;}</style>5.3 调试与错误处理
<template> <div v-if="hasError" class="error-boundary"> <h3>组件加载失败</h3> <p>{{ errorMessage }}</p> <button @click="retry">重试</button> </div> <slot v-else /></template>
<script setup>import { ref, onErrorCaptured } from 'vue';
const hasError = ref(false);const errorMessage = ref('');
onErrorCaptured((err) => { hasError.value = true; errorMessage.value = err.message; console.error('MDX 组件错误:', err); return false; // 阻止错误继续向上传播});
const retry = () => { hasError.value = false; errorMessage.value = '';};</script>---// 使用错误边界包装可能出错的组件import MdxErrorBoundary from '../../components/vue/MdxErrorBoundary.vue';import ExperimentalComponent from '../../components/vue/ExperimentalComponent.vue';
title: '错误处理示例'---
# 健壮的 MDX 内容
## 使用错误边界
<MdxErrorBoundary client:load> <ExperimentalComponent :data="complexData" /></MdxErrorBoundary>
## 备用内容
如果上面的组件加载失败,错误边界会显示备用界面,而不是破坏整个页面。六、实际应用案例
6.1 交互式技术文档
---import ApiPlayground from '../../components/vue/ApiPlayground.vue';import ResponseVisualizer from '../../components/vue/ResponseVisualizer.vue';import CodeSnippet from '../../components/CodeSnippet.astro';
title: 'API 文档 - 用户服务'description: '交互式 API 文档,可直接测试端点'tags: ['api', 'rest', 'interactive']---
# 用户服务 API
## GET /api/users
获取用户列表。
### 请求示例
<CodeSnippet language="javascript">// 获取用户列表fetch('/api/users') .then(response => response.json()) .then(data => console.log(data));</CodeSnippet>
### 实时测试
<ApiPlayground client:load endpoint="/api/users" method="GET" :headers="{ 'Authorization': 'Bearer token' }"/>
### 响应结构
<ResponseVisualizer client:visible :response="{ success: true, data: [ { id: 1, name: '张三', email: 'zhangsan@example.com', role: 'user' } ], pagination: { page: 1, limit: 20, total: 100 } }"/>6.2 交互式产品演示
---import DashboardDemo from '../../components/vue/DashboardDemo.vue';import FeatureToggle from '../../components/vue/FeatureToggle.vue';import DataExport from '../../components/vue/DataExport.vue';
title: '产品仪表板演示'description: '交互式产品功能演示'product: 'Analytics Pro'version: '2.0'---
# 数据分析仪表板 - 交互演示
## 实时仪表板
<DashboardDemo client:load :initialView="'overview'" :demoData="demoDataset" :features="{ realtime: true, filters: true, export: true }"/>
## 功能配置
### 1. 实时数据刷新
<FeatureToggle client:load feature="realtime" label="启用实时数据" description="每 5 秒自动刷新数据" :defaultEnabled="true"/>
### 2. 数据导出选项
<DataExport client:idle :formats="['CSV', 'JSON', 'Excel', 'PDF']" :defaultFormat="'CSV'" :includeOptions="{ charts: true, tables: true, filters: true }"/>6.3 交互式教育内容
---import CodeRunner from '../../components/vue/CodeRunner.vue';import InteractiveQuiz from '../../components/vue/InteractiveQuiz.vue';import ConceptVisualizer from '../../components/vue/ConceptVisualizer.vue';
title: 'JavaScript 基础 - 交互式课程'description: '通过实践学习 JavaScript 基础'level: 'beginner'estimatedTime: '30分钟'---
# JavaScript 变量与数据类型
## 实践练习
### 1. 变量声明
尝试下面的代码编辑器:
<CodeRunner client:load language="javascript" :initialCode="`// 声明一个变量let message = 'Hello World';
// 修改变量的值message = 'Hello JavaScript';
console.log(message); `" :testCases="[ { input: '', expectedOutput: 'Hello JavaScript', description: '应该输出修改后的消息' } ]"/>
### 2. 数据类型可视化
<ConceptVisualizer client:visible concept="dataTypes" :examples="{ string: 'Hello World', number: 42, boolean: true, array: [1, 2, 3], object: { name: 'John', age: 30 } }"/>
### 3. 理解测验
<InteractiveQuiz client:load :questions="[ { question: 'let 和 const 的区别是什么?', type: 'multiple-choice', options: [ 'let 可重新赋值,const 不可', 'const 用于常量,let 用于变量', '两者完全相同', 'let 是块级作用域,const 不是' ], correctAnswers: [0, 1], explanation: 'let 允许重新赋值,const 用于声明常量' } ]" :passingScore="80"/>七、总结与部署
7.1 构建与部署注意事项
// astro.config.mjs - 生产配置import { defineConfig } from 'astro/config';import mdx from '@astrojs/mdx';import vue from '@astrojs/vue';import compress from 'astro-compress';
export default defineConfig({ output: 'static', // 或 'server' 用于 SSR integrations: [ mdx({ optimize: { split: true, minify: true, }, }), vue({ // 生产环境 Vue 配置 template: { compilerOptions: { isCustomElement: (tag) => tag.includes('-'), }, }, }), compress({ CSS: true, HTML: true, JavaScript: true, Image: false, // 由 Astro 的 Image 组件处理 }), ], build: { // 拆分 MDX 块 rollupOptions: { output: { manualChunks(id) { if (id.includes('mdx')) { return 'mdx-bundle'; } if (id.includes('vue')) { return 'vue-components'; } }, }, }, },});7.2 监控与分析
<template> <!-- 跟踪 MDX 交互 --></template>
<script setup>import { onMounted, onUnmounted } from 'vue';
const props = defineProps({ contentId: String, contentType: String,});
// 跟踪组件使用onMounted(() => { // 发送分析事件 trackEvent('mdx_component_view', { component: props.contentId, type: props.contentType, timestamp: Date.now(), });
// 跟踪交互 const interactiveElements = document.querySelectorAll('[data-interactive]'); interactiveElements.forEach(el => { el.addEventListener('click', trackInteraction); });});
onUnmounted(() => { // 清理事件监听器});
const trackEvent = (event, data) => { if (typeof window.gtag !== 'undefined') { window.gtag('event', event, data); }};
const trackInteraction = (event) => { trackEvent('mdx_interaction', { element: event.target.dataset.interactive, action: event.type, });};</script>7.3 内容更新策略
# 内容发布流程开发流程: 1. 在 content/ 目录创建或编辑 .mdx 文件 2. 添加或更新 Vue 组件 3. 本地测试: npm run dev 4. 构建检查: npm run build 5. 提交到版本控制
CI/CD 流程: 1. 自动构建和测试 2. 预览部署 3. 内容审核 4. 生产部署
内容更新频率: - 技术文档: 实时更新 - 教程内容: 每周更新 - 产品演示: 每月更新 - 营销内容: 按需更新八、资源与扩展
8.1 推荐的 Vue 组件库
---// 在 MDX 中使用的推荐 Vue 组件库import VueComponentsGuide from '../../components/VueComponentsGuide.astro';
title: '推荐的 Vue 组件库'---
# 适用于 MDX 的 Vue 组件库
<VueComponentsGuide />
以下库特别适合在 Astro MDX 中使用:
## 1. 数据可视化- **Chart.js + vue-chartjs**: 轻量级图表- **ApexCharts**: 交互式图表- **Vega-Lite**: 声明式可视化
## 2. UI 组件- **PrimeVue**: 完整的企业级组件- **Element Plus**: 桌面端 UI 库- **Vuetify**: Material Design 实现
## 3. 特殊交互- **Vue Flow**: 流程图和节点图- **Vue Formulate**: 表单构建- **Vue Tour**: 引导式教程8.2 学习资源
8.3 社区资源
// 有用的社区插件const mdxPlugins = [ 'remark-gfm', // GitHub Flavored Markdown 'remark-math', // 数学公式 'rehype-katex', // KaTeX 渲染 'remark-toc', // 自动生成目录 'remark-autolink-headings', // 自动链接标题 'rehype-slug', // 添加 slug ID 'rehype-external-links', // 外部链接处理];总结
Astro 中的 MDX 提供了前所未有的内容创作能力,特别适合需要:
- 技术文档:交互式 API 文档、代码示例
- 教育内容:交互式教程、在线课程
- 产品演示:可操作的产品展示
- 营销页面:动态的内容营销
通过结合 Vue 的动态组件能力,MDX 不再是静态的文档格式,而是变成了一个完整的交互式内容平台。
关键优势:
- ✅ 内容与交互分离:内容团队写 Markdown,开发团队写组件
- ✅ 渐进式增强:从静态内容开始,逐步添加交互
- ✅ 性能优化:Astro 确保只有必要的 JavaScript 被发送
- ✅ 开发者友好:熟悉的 Vue 开发体验
适用场景:
- 📚 技术文档和 API 参考
- 🎓 在线教育和培训材料
- 🛒 产品演示和配置器
- 📊 数据报告和分析仪表板
- 🎨 设计系统和组件库文档
通过合理的设计和实现,Astro + MDX + Vue 的组合可以创建出既高性能又高度交互的现代 Web 内容体验。
赞助支持
如果这篇文章对你有帮助,欢迎赞助支持!
MDX 在 Astro 中的高级应用
https://march7th.online/posts/mdx-在-astro-中的高级应用/ 最后更新于 2025-12-07,距今已过 11 天
部分内容可能已过时
March7th