|
|
# Использование Vue в Markdown {#using-vue-in-markdown}
|
|
|
|
|
|
В VitePress каждый Markdown-файл компилируется в HTML, а затем обрабатывается как [однофайловый компонент Vue](https://ru.vuejs.org/guide/scaling-up/sfc.html). Это означает, что вы можете использовать любые возможности Vue внутри Markdown, включая динамический шаблонизатор, использование компонентов Vue или произвольную логику компонентов Vue на странице, добавив тег `<script>`.
|
|
|
|
|
|
Стоит отметить, что VitePress использует компилятор Vue для автоматического обнаружения и оптимизации чисто статических частей контента в формате Markdown. Статичное содержимое оптимизируется в отдельные узлы-заполнители и исключается из полезной нагрузки JavaScript страницы при первых посещениях. Они также пропускаются при гидратации на стороне клиента. Короче говоря, вы платите только за динамические части на каждой конкретной странице.
|
|
|
|
|
|
::: tip Совместимость с SSR
|
|
|
Всё, что используется в Vue, должно быть совместимо с SSR. Подробности и общие обходные пути см. в главе [Совместимость с SSR](./ssr-compat).
|
|
|
:::
|
|
|
|
|
|
## Шаблонизация {#templating}
|
|
|
|
|
|
### Интерполяция {#interpolation}
|
|
|
|
|
|
Каждый файл Markdown сначала компилируется в HTML, а затем передается в качестве компонента Vue в конвейер процесса Vite. Это означает, что вы можете использовать интерполяцию в стиле Vue в тексте:
|
|
|
|
|
|
**Разметка**
|
|
|
|
|
|
```md
|
|
|
{{ 1 + 1 }}
|
|
|
```
|
|
|
|
|
|
**Результат**
|
|
|
|
|
|
<div class="language-text"><pre><code>{{ 1 + 1 }}</code></pre></div>
|
|
|
|
|
|
### Директивы {#directives}
|
|
|
|
|
|
Директивы также работают (обратите внимание, что по замыслу необработанный HTML также допустим в Markdown):
|
|
|
|
|
|
**Разметка**
|
|
|
|
|
|
```html
|
|
|
<span v-for="i in 3">{{ i }}</span>
|
|
|
```
|
|
|
|
|
|
**Результат**
|
|
|
|
|
|
<div class="language-text"><pre><code><span v-for="i in 3">{{ i }} </span></code></pre></div>
|
|
|
|
|
|
## `<script>` и `<style>` {#script-and-style}
|
|
|
|
|
|
Теги корневого уровня `<script>` и `<style>` в Markdown-файлах работают так же, как и в Vue SFC, включая `<script setup>`, `<style module>` и т. д. Главное отличие заключается в отсутствии тега `<template>`: всё остальное содержимое корневого уровня — Markdown. Также обратите внимание, что все теги должны располагаться **после** метаданных:
|
|
|
|
|
|
```html
|
|
|
---
|
|
|
hello: world
|
|
|
---
|
|
|
|
|
|
<script setup>
|
|
|
import { ref } from 'vue'
|
|
|
|
|
|
const count = ref(0)
|
|
|
</script>
|
|
|
|
|
|
## Содержание в формате Markdown. Счётчик: {{ count }}
|
|
|
|
|
|
<button :class="$style.button" @click="count++">Увеличить</button>
|
|
|
|
|
|
<style module>
|
|
|
.button {
|
|
|
color: red;
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
</style>
|
|
|
```
|
|
|
|
|
|
::: warning Избегайте `<style scoped>` в Markdown
|
|
|
При использовании в Markdown `<style scoped>` требует добавления специальных атрибутов к каждому элементу на текущей странице, что значительно увеличивает размер страницы. `<style module>` предпочтительнее, когда на странице требуется локально копируемый стиль.
|
|
|
:::
|
|
|
|
|
|
У вас также есть доступ к runtime API VitePress, например, к [хелперу `useData`](../reference/runtime-api#usedata), который предоставляет доступ к метаданным текущей страницы:
|
|
|
|
|
|
**Разметка**
|
|
|
|
|
|
```html
|
|
|
<script setup>
|
|
|
import { useData } from 'vitepress'
|
|
|
|
|
|
const { page } = useData()
|
|
|
</script>
|
|
|
|
|
|
<pre>{{ page }}</pre>
|
|
|
```
|
|
|
|
|
|
**Результат**
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"path": "/using-vue.html",
|
|
|
"title": "Использование Vue в Markdown",
|
|
|
"frontmatter": {},
|
|
|
...
|
|
|
}
|
|
|
```
|
|
|
|
|
|
## Использование компонентов {#using-components}
|
|
|
|
|
|
Вы можете импортировать и использовать компоненты Vue непосредственно в файлах Markdown.
|
|
|
|
|
|
### Импорт в Markdown {#importing-in-markdown}
|
|
|
|
|
|
Если компонент используется только на нескольких страницах, рекомендуется явно импортировать его туда, где он используется. Это позволяет правильно разделить их по коду и загружать только при показе соответствующих страниц:
|
|
|
|
|
|
```md
|
|
|
<script setup>
|
|
|
import CustomComponent from '../components/CustomComponent.vue'
|
|
|
</script>
|
|
|
|
|
|
# Документация
|
|
|
|
|
|
Это .md с использованием пользовательского компонента
|
|
|
|
|
|
<CustomComponent />
|
|
|
|
|
|
## Другая документация
|
|
|
|
|
|
...
|
|
|
```
|
|
|
|
|
|
### Глобальная регистрация компонентов {#registering-components-globally}
|
|
|
|
|
|
Если компонент будет использоваться на большинстве страниц, его можно зарегистрировать глобально, настроив экземпляр приложения Vue. Пример смотрите в соответствующей главе [Расширение темы по умолчанию](./extending-default-theme#registering-global-components).
|
|
|
|
|
|
::: warning ВАЖНО
|
|
|
Убедитесь, что имя пользовательского компонента содержит дефис или написано в PascalCase. В противном случае он будет рассматриваться как встроенный элемент и заключен в тег `<p>`, что приведет к несоответствию гидратации, поскольку `<p>` не позволяет размещать внутри него блочные элементы.
|
|
|
:::
|
|
|
|
|
|
### Использование компонентов в заголовках <ComponentInHeader /> {#using-components-in-headers}
|
|
|
|
|
|
Вы можете использовать компоненты Vue в заголовках, но обратите внимание на разницу между следующими синтаксисами:
|
|
|
|
|
|
| Markdown | Итоговый HTML | Разобранный заголовок |
|
|
|
| -------------------------------------------------------- | ------------------------------------------ | --------------------- |
|
|
|
| <pre v-pre><code> # текст <Tag/> </code></pre> | `<h1>текст <Tag/></h1>` | `текст` |
|
|
|
| <pre v-pre><code> # текст \`<Tag/>\` </code></pre> | `<h1>текст <code><Tag/></code></h1>` | `текст <Tag/>` |
|
|
|
|
|
|
HTML, обёрнутый `<code>`, будет отображаться как есть; только тот HTML, который **не** обёрнут, будет разобран Vue.
|
|
|
|
|
|
::: tip ПРИМЕЧАНИЕ
|
|
|
Вывод HTML осуществляется с помощью [Markdown-it](https://github.com/Markdown-it/Markdown-it), а парсинг заголовков обрабатывается VitePress (и используется как для боковой панели, так и для заголовка документа).
|
|
|
:::
|
|
|
|
|
|
## Экранирование {#escaping}
|
|
|
|
|
|
Вы можете избежать интерполяций Vue, обернув их в `<span>` или другие элементы с помощью директивы `v-pre`:
|
|
|
|
|
|
**Разметка**
|
|
|
|
|
|
```md
|
|
|
Это <span v-pre>{{ будет отображаться как есть}}</span>.
|
|
|
```
|
|
|
|
|
|
**Результат**
|
|
|
|
|
|
<div class="escape-demo">
|
|
|
<p>Это <span v-pre>{{ будет отображаться как есть}}</span></p>
|
|
|
</div>
|
|
|
|
|
|
В качестве альтернативы вы можете обернуть весь абзац в пользовательский контейнер `v-pre`:
|
|
|
|
|
|
```md
|
|
|
::: v-pre
|
|
|
{{ Это будет отображаться как есть }}
|
|
|
:::
|
|
|
```
|
|
|
|
|
|
**Результат**
|
|
|
|
|
|
<div class="escape-demo">
|
|
|
|
|
|
::: v-pre
|
|
|
{{ Это будет отображаться как есть }}
|
|
|
:::
|
|
|
|
|
|
</div>
|
|
|
|
|
|
## Unescape в блоках кода {#unescape-in-code-blocks}
|
|
|
|
|
|
По умолчанию все изолированные блоки кода автоматически оборачиваются `v-pre`, поэтому внутри них не будет обрабатываться синтаксис Vue. Чтобы включить интерполяцию в стиле Vue внутри фигурных скобок, вы можете добавить к языку суффикс `-vue`, например `js-vue`:
|
|
|
|
|
|
**Разметка**
|
|
|
|
|
|
````md
|
|
|
```js-vue
|
|
|
Привет, {{ 1 + 1 }}
|
|
|
```
|
|
|
````
|
|
|
|
|
|
**Результат**
|
|
|
|
|
|
```js-vue
|
|
|
Привет, {{ 1 + 1 }}
|
|
|
```
|
|
|
|
|
|
Обратите внимание, что при этом некоторые лексемы могут не выделяться синтаксисом должным образом.
|
|
|
|
|
|
## Использование препроцессоров CSS {#using-css-pre-processors}
|
|
|
|
|
|
VitePress имеет [встроенную поддержку](https://vitejs.dev/guide/features.html#css-pre-processors) для препроцессоров CSS: файлы `.scss`, `.sass`, `.less`, `.styl` и `.stylus`. Для них не нужно устанавливать специфические для Vite плагины, но сам соответствующий препроцессор должен быть установлен:
|
|
|
|
|
|
```
|
|
|
# .scss и .sass
|
|
|
npm install -D sass
|
|
|
|
|
|
# .less
|
|
|
npm install -D less
|
|
|
|
|
|
# .styl и .stylus
|
|
|
npm install -D stylus
|
|
|
```
|
|
|
|
|
|
Затем вы можете использовать следующее в Markdown и компонентах темы:
|
|
|
|
|
|
```vue
|
|
|
<style lang="sass">
|
|
|
.title
|
|
|
font-size: 20px
|
|
|
</style>
|
|
|
```
|
|
|
|
|
|
## Использование телепортов {#using-teleports}
|
|
|
|
|
|
В настоящее время VitePress поддерживает SSG только для телепортов к элементу `body`. Для других целей вы можете обернуть их внутри встроенного компонента `<ClientOnly>` или внедрить разметку телепортации в нужное место HTML конечной страницы через [хук `postRender`](../reference/site-config#postrender).
|
|
|
|
|
|
<ModalDemo />
|
|
|
|
|
|
::: details Исходный код
|
|
|
<<< @/ru/components/ModalDemo.vue
|
|
|
:::
|
|
|
|
|
|
```md
|
|
|
<ClientOnly>
|
|
|
<Teleport to="#modal">
|
|
|
<div>
|
|
|
// ...
|
|
|
</div>
|
|
|
</Teleport>
|
|
|
</ClientOnly>
|
|
|
```
|
|
|
|
|
|
<script setup>
|
|
|
import ModalDemo from '../components/ModalDemo.vue'
|
|
|
import ComponentInHeader from '../../components/ComponentInHeader.vue'
|
|
|
</script>
|
|
|
|
|
|
<style>
|
|
|
.escape-demo {
|
|
|
border: 1px solid var(--vp-c-border);
|
|
|
border-radius: 8px;
|
|
|
padding: 0 20px;
|
|
|
}
|
|
|
</style>
|