You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vitepress/docs/ru/guide/using-vue.md

254 lines
12 KiB

# Использование 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> # текст &lt;Tag/&gt; </code></pre> | `<h1>текст <Tag/></h1>` | `текст` |
| <pre v-pre><code> # текст \`&lt;Tag/&gt;\` </code></pre> | `<h1>текст <code>&lt;Tag/&gt;</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>