在 Markdown 中使用 Vue
在 VitePress 中,每個 Markdown 檔案會編譯成 HTML,然後當作 Vue 單一檔案元件 處理。這表示您可以在 Markdown 中使用任何 Vue 功能,包括動態範本、使用 Vue 元件,或透過新增 <script>
標籤新增任意頁面內 Vue 元件邏輯。
值得注意的是,VitePress 採用 Vue 的編譯器自動偵測並最佳化 Markdown 內容中純靜態的部分。靜態內容會最佳化成單一佔位符節點,並從頁面的 JavaScript 負載中移除,以進行首次造訪。它們也會在用戶端水化期間略過。簡而言之,您只會為任何特定頁面上的動態部分付費。
SSR 相容性
所有 Vue 使用都必須與 SSR 相容。請參閱 SSR 相容性 以取得詳細資訊和常見的解決方法。
範本
內插
每個 Markdown 檔案會先編譯成 HTML,然後傳遞給 Vite 處理程序管道,當作 Vue 元件。這表示您可以在文字中使用 Vue 風格的內插
輸入
{{ 1 + 1 }}
輸出
2
指令
指令也適用(請注意,根據設計,原始 HTML 在 Markdown 中也同樣有效)
輸入
<span v-for="i in 3">{{ i }}</span>
輸出
1 2 3
<script>
和 <style>
Markdown 檔案中的根層級 <script>
和 <style>
標籤就像在 Vue SFC 中一樣運作,包括 <script setup>
、<style module>
等。這裡的主要差別在於沒有 <template>
標籤:所有其他根層級內容都是 Markdown。另外請注意,所有標籤都應該放在frontmatter 之後
---
hello: world
---
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
## Markdown Content
The count is: {{ count }}
<button :class="$style.button" @click="count++">Increment</button>
<style module>
.button {
color: red;
font-weight: bold;
}
</style>
在 Markdown 中避免使用 <style scoped>
在 Markdown 中使用時,<style scoped>
需要為當前頁面上的每個元素新增特殊屬性,這將大幅增加頁面大小。當頁面需要局部範圍的樣式時,建議使用 <style module>
。
您還可以存取 VitePress 的執行時期 API,例如 useData
輔助函式,它提供存取當前頁面元資料的功能
輸入
<script setup>
import { useData } from 'vitepress'
const { page } = useData()
</script>
<pre>{{ page }}</pre>
輸出
{
"path": "/using-vue.html",
"title": "Using Vue in Markdown",
"frontmatter": {},
...
}
使用元件
您可以在 Markdown 檔案中直接匯入和使用 Vue 元件。
在 Markdown 中匯入
如果元件只在少數頁面中使用,建議在使用它們的地方明確匯入。這允許它們適當地進行程式碼分割,並且只在顯示相關頁面時載入
<script setup>
import CustomComponent from '../components/CustomComponent.vue'
</script>
# Docs
This is a .md using a custom component
<CustomComponent />
## More docs
...
全域註冊元件
如果元件將在大部分頁面上使用,它們可以透過自訂 Vue 應用程式實例來進行全域註冊。請參閱 擴充預設佈景主題 中相關區段以取得範例。
重要
請確保自訂元件的名稱包含連字號或使用 PascalCase。否則,它將被視為內嵌元素並封裝在 <p>
標籤內,這將導致水化不匹配,因為 <p>
不允許在其中放置區塊元素。
在標題中使用元件 ⚡
您可以在標題中使用 Vue 元件,但請注意以下語法的差異
Markdown | 輸出 HTML | 已剖析標題 |
---|---|---|
| <h1>文字 <Tag/></h1> | 文字 |
| <h1>文字 <code><Tag/></code></h1> | 文字 <Tag/> |
由 <code>
包起來的 HTML 將會原樣顯示;只有未包起來的 HTML 才會被 Vue 剖析。
提示
輸出 HTML 是由 Markdown-it 完成的,而已剖析的標題則是由 VitePress 處理(並同時用於側邊欄和文件標題)。
跳脫
您可以透過將 Vue 插值包在 <span>
或其他具有 v-pre
指令的元素中來跳脫它們
輸入
This <span v-pre>{{ will be displayed as-is }}</span>
輸出
這 {{ 將會原樣顯示 }}
或者,您可以將整個段落包在 v-pre
自訂容器中
::: v-pre
{{ This will be displayed as-is }}
:::
輸出
{{ 這將會原樣顯示 }}
在程式碼區塊中取消跳脫
預設情況下,所有圍欄式程式碼區塊都會自動以 v-pre
包起來,因此不會處理區塊內的任何 Vue 語法。若要在圍欄內啟用 Vue 風格的插值,您可以將語言加上 -vue
字尾,例如 js-vue
輸入
```js-vue
Hello {{ 1 + 1 }}
```
輸出
Hello 2
請注意,這可能會導致某些代碼無法正確地以語法高亮顯示。
使用 CSS 預處理器
VitePress 內建支援 CSS 預處理器:.scss
、.sass
、.less
、.styl
和 .stylus
檔案。不需要為它們安裝 Vite 特定的外掛程式,但必須安裝對應的預處理器本身
# .scss and .sass
npm install -D sass
# .less
npm install -D less
# .styl and .stylus
npm install -D stylus
然後您可以在 Markdown 和佈景主題元件中使用以下內容
<style lang="sass">
.title
font-size: 20px
</style>
使用傳送
Vitepress 目前僅支援傳送至主體的 SSG。對於其他目標,您可以將它們包在內建的 <ClientOnly>
元件中,或透過 postRender
鉤子 將傳送標記注入至最終頁面 HTML 中正確的位置。
Details
<script setup lang="ts">
import { ref } from 'vue'
const showModal = ref(false)
</script>
<template>
<button class="modal-button" @click="showModal = true">Show Modal</button>
<Teleport to="body">
<Transition name="modal">
<div v-show="showModal" class="modal-mask">
<div class="modal-container">
<p>Hello from the modal!</p>
<div class="model-footer">
<button class="modal-button" @click="showModal = false">
Close
</button>
</div>
</div>
</div>
</Transition>
</Teleport>
</template>
<style scoped>
.modal-mask {
position: fixed;
z-index: 200;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
transition: opacity 0.3s ease;
}
.modal-container {
width: 300px;
margin: auto;
padding: 20px 30px;
background-color: var(--vp-c-bg);
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
transition: all 0.3s ease;
}
.model-footer {
margin-top: 8px;
text-align: right;
}
.modal-button {
padding: 4px 8px;
border-radius: 4px;
border-color: var(--vp-button-alt-border);
color: var(--vp-button-alt-text);
background-color: var(--vp-button-alt-bg);
}
.modal-button:hover {
border-color: var(--vp-button-alt-hover-border);
color: var(--vp-button-alt-hover-text);
background-color: var(--vp-button-alt-hover-bg);
}
.modal-enter-from,
.modal-leave-to {
opacity: 0;
}
.modal-enter-from .modal-container,
.modal-leave-to .modal-container {
transform: scale(1.1);
}
</style>
<ClientOnly>
<Teleport to="#modal">
<div>
// ...
</div>
</Teleport>
</ClientOnly>