# 在 VitePress 中创建支持演示与源码查看的 Demo 组件

URL: https://caijiao.org/posts/10
Source: docs/posts/10.md
Description: 本文介绍如何在 VitePress 中自定义一个 Vue 组件，实现示例 HTML 的实时演示与源码查看功能，支持 iframe 加载、Ace Editor 源码查看与复制功能。

在编写技术文档（例如教程或组件库文档）时，我们常常希望能 **在页面中直接演示 [HTML](/html/) 示例**，并同时 **支持查看源码与复制功能**。  
本文将介绍如何在 **VitePress** 项目中创建一个功能完善的 `<Demo>` 组件。

## 1️⃣ 功能概述

本文实现的 Demo 组件具有以下特性：

✅ 支持以 iframe 加载外部 HTML 文件（如 `/demos/3.html`）  
✅ 自动检测路径错误（防止加载到 `index.html`）  
✅ 源码高亮显示（基于 **Ace Editor**）  
✅ 一键复制源码  
✅ 切换演示 / 查看源码  
✅ 自动调整 iframe 高度  
✅ 兼容 VitePress 的 SSR 和静态构建模式  

## 2️⃣ 文件结构示例

在 VitePress 项目中，我们推荐将组件放置在：

```txt
.vitepress/
└── theme/
└── components/
└── Demo.vue
```

同时，你的示例 HTML 文件可以放在 `/public/demos/` 下，例如：

```txt
public/
└── demos/
├── 1.html
├── 2.html
└── 3.html
````

## 3️⃣ 安装依赖

本组件使用 [vue3-ace-editor](https://github.com/CarterLi/vue3-ace-editor) 作为源码查看器，因此需要安装：

```bash
pnpm add vue3-ace-editor ace-builds
````

或使用 npm：

```bash
npm install vue3-ace-editor ace-builds
```

## 4️⃣ 组件源码

创建文件：
`./.vitepress/theme/components/Demo.vue`

```vue
<!-- Demo.vue -->


<template>
  <div class="demo-block">
    <div class="demo-header">
      <div class="demo-actions">
        <button class="btn" @click="showSource = !showSource">
          {{ showSource ? '显示演示' : '查看源码' }}
        </button>
        <button class="btn" @click="copySource">
          {{ copyState || '复制源码' }}
        </button>
      </div>
    </div>

    <div v-if="errorMsg" class="demo-error">{{ errorMsg }}</div>

    <div v-if="!showSource" class="demo-preview">
      <div v-if="iframeSrc" class="iframe-wrap">
        <iframe ref="iframeRef" :src="iframeSrc" @load="adjustHeight" frameborder="0" style="width:100%"></iframe>
      </div>
      <div v-else class="demo-fallback">
        <p>示例无法以 iframe 加载（请检查路径或将 demo 放到 public/）。</p>
      </div>
    </div>

    <div v-else class="demo-editor">
      <v-ace-editor v-model:value="sourceCode" lang="html" theme="github" :readonly="true"
        style="width:100%; height: 420px; font-size:13px;" />
    </div>
  </div>
</template>


```

## 5️⃣ 使用方式

在 Markdown 文档中直接引入：

```md

```

或者使用相对路径（VitePress 会自动解析）：

```md

```

> 💡 注意：请确保示例文件放在 `public/demos/` 目录下，否则可能被 Vite fallback 到 `index.html`。

## 6️⃣ 示例效果

你将看到如下效果：

* 默认显示 HTML 示例（通过 iframe 渲染）
* 点击「查看源码」切换至源码查看界面
* 点击「复制源码」即可复制 HTML 内容到剪贴板

## 7️⃣ 总结

通过以上实现，我们得到了一个高复用的 `<Demo>` 组件，完美支持：

* ✅ 示例与源码双模式展示
* ✅ 独立 iframe 隔离运行环境
* ✅ 一键复制源码
* ✅ 兼容 VitePress 的本地与生产模式

非常适合在技术教程或组件文档中集成交互示例。
