自訂渲染
只有在您想擁有整個圖表體驗時才使用自訂渲染器(custom renderer)。
若只需要外圍版面、共用載入介面或錯誤呈現,請改為包裝 <Mermaid>,保留內建渲染器。
了解渲染器選擇
將 components.renderer 設為 ~/components 中元件的名稱:
export default defineNuxtConfig({
contentMermaid: {
components: {
renderer: 'CustomMermaid',
spinner: 'MermaidSpinner',
},
},
})
設定的名稱是自訂渲染器候選項(Custom Renderer Candidate)。
用戶端上,套件會遞迴搜尋 ~/components,找出相符檔名;比對會忽略大小寫、空格、底線、連字號、路徑區段與選用的 .vue 副檔名。
| 解析結果 | 渲染擁有者(Rendering Owner) |
|---|---|
| 沒有渲染器名稱 | 內建渲染器(Built-in Renderer)。 |
| 候選項載入中 | 尚未有渲染器;預設原始碼備援內容保持可見。 |
| 候選項解析成功 | 自訂渲染器,且獨占所有權。 |
| 找不到候選項或載入失敗 | 顯示主控台診斷訊息後使用內建渲染器。 |
對每個已解析的候選項,這是單向的所有權選擇。
之後自訂渲染器若掛載或渲染失敗,不會再觸發第二次內建備援。
它的載入與錯誤介面、主題決策、Mermaid 呼叫、工具列、全螢幕、展開與可存取性行為都必須由您實作。
實作完整的自訂渲染器
解析成功的自訂渲染器只會收到以下擴充輸入(extension inputs):
code:呼叫端傳入時,已解碼的 Mermaid 原始碼。spinner:設定的載入指示元件,或套件的載入指示備援元件。- 預設插槽(slot):由
<Mermaid>提供的原始碼備援內容。
它不會收到內建的 pageConfig、直接 config、工具列選項、載入插槽、錯誤插槽、自動主題解析或 components.error。請明確擁有這些關切點:
<!-- components/CustomMermaid.vue -->
<script setup lang="ts">
import { onMounted, ref, shallowRef, useId } from 'vue'
import type { Component } from 'vue'
const props = defineProps<{
code?: string
spinner: Component | string
}>()
const loading = ref(true)
const error = shallowRef<unknown>()
const svg = ref('')
const renderId = `custom-mermaid-${useId().replaceAll(':', '')}`
onMounted(async () => {
try {
const mermaid = await useNuxtApp().$mermaid()
svg.value = (await mermaid.render(renderId, props.code ?? '')).svg
}
catch (cause) {
error.value = cause
}
finally {
loading.value = false
}
})
</script>
<template>
<section class="custom-mermaid">
<component :is="props.spinner" v-if="loading" />
<p v-else-if="error" role="alert">
Diagram failed: {{ error instanceof Error ? error.message : String(error) }}
</p>
<div v-else v-html="svg" />
</section>
</template>
此範例刻意自行擁有失敗呈現。若自訂渲染器需要主題變更或 Mermaid 設定,請提供並回應自己的應用程式層級狀態,而不要期待內建渲染器的屬性(props)。
改為包裝內建渲染器
不要把這個外層元件(wrapper)設為 components.renderer。
它是一般的應用程式元件:在加入呈現外觀時,仍保留內建的設定、互動、載入與錯誤行為:
<!-- components/DiagramCard.vue -->
<script setup lang="ts">
const props = defineProps<{
title: string
source: string
}>()
const encodedSource = computed(() => encodeURIComponent(props.source))
</script>
<template>
<section class="diagram-card">
<h2>{{ title }}</h2>
<Mermaid :code="encodedSource">
<template #loading>
<p aria-live="polite">正在渲染圖表…</p>
</template>
<template #error="{ error, source }">
<p role="alert">
Render failed: {{ error instanceof Error ? error.message : String(error) }}
</p>
<details>
<summary>顯示 Mermaid 原始碼</summary>
<pre><code>{{ source }}</code></pre>
</details>
</template>
</Mermaid>
</section>
</template>
若 Nuxt 設定未自動匯入 Vue 工具函式,請加入 import { computed } from 'vue'。
內建渲染器接受預設插槽作為原始碼備援內容、#loading 作為初始載入狀態,以及 #error="{ error, source }" 作為 Mermaid 渲染失敗。或者可由 components.error 提供全域內建錯誤元件,並接收 error 與 source;自訂渲染器不會使用它。
避免遞迴渲染器選擇
絕對不要在設定為 components.renderer 的元件中渲染 <Mermaid>。巢狀元件會重複選擇候選項,可能無限遞迴。
請改為呼叫 useNuxtApp().$mermaid()、另一個渲染器,或獨立的較低層實作。只有未被設定為自訂渲染器的外層元件才是安全的。