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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Использование 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>