API reference
useContent()
Функция useContent()
извлекает ближайшую информацию о содержимом для текущего маршрута. Возвращаемый объект включает в себя:
headings: ContentHeading[] | undefined;
menu: ContentMenu | undefined;
Массив headings
содержит данные об элементах заголовка html <h1>
- <h6>
из файлов разметки.
Меню - это контекстные данные, объявленные в файлах menu.md
. Дополнительную информацию о формате и местоположении файла см. в разделе определение файла меню.
useDocumentHead()
Функция useDocumentHead()
используется для чтения метаданных заголовка документа.
useDocumentHead()
извлекает объект DocumentHead
, доступный только для чтения, который включает:
export interface DocumentHead {
/**
* Представляет собой элемент `<title>` документа.
*/
readonly title?: string;
/**
* Используется для ручной установки метатегов в заголовке. Кроме того,
* свойство `data` может быть использовано для вставки произвольных данных,
* которые компонент `<head>` в дальнейшем может использовать для генерации тегов `<meta>`.
*/
readonly meta?: readonly DocumentMeta[];
/**
* Используется для ручного добавления элементов `<link>` к `<head>`.
*/
readonly links?: readonly DocumentLink[];
/**
* Используется для ручного добавления элементов `<style>` к `<head>`.
*/
readonly styles?: readonly DocumentStyle[];
/**
* Произвольный объект, содержащий пользовательские данные. При создании `<head>` из
* markdown-файлов, атрибуты frontmatter, которые не распознаются как известные
* мета-имена (такие как title, description, author и т.д.), хранятся в этом свойстве.
*/
readonly frontmatter?: Readonly<Record<string, any>>;
}
Все стартовые шаблоны включают компонент <RouterHead>
, который отвечает за генерацию элемента <head>
документа. Он использует функцию useDocumentHead()
для получения текущих метаданных заголовка и вывода соответствующих элементов <meta>
, <link>
, <style>
и <title>
.
import { component$ } from '@builder.io/qwik';
import { useDocumentHead } from '@builder.io/qwik-city';
/**
* Компонент RouterHead размещается внутри элемента `<head>` документа.
*/
export const RouterHead = component$(() => {
const head = useDocumentHead();
return (
<>
<title>{head.title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
{head.meta.map((m) => (
<meta {...m} />
))}
{head.links.map((l) => (
<link {...l} />
))}
{head.styles.map((s) => (
<style {...s.props} dangerouslySetInnerHTML={s.style} />
))}
</>
);
});
useLocation()
Используйте функцию useLocation()
для получения объекта RouteLocation
текущего маршрута.
useLocation()
позволяет разработчикам узнать текущий URL, параметры, а также то, осуществляет ли приложение в данный момент навигацию, что полезно для показа индикатора загрузки.
export interface RouteLocation {
/**
* Параметры маршрута, извлечённые из URL-адреса.
*/
readonly params: Record<string, string>;
/**
* Текущий URL-адрес.
*/
readonly url: URL;
/**
* True, если приложение в данный момент осуществляет навигацию.
*/
readonly isNavigating: boolean;
}
Возвращаемое значение useLocation()
аналогично объекту document.location
, но его безопасно использовать на сервере, где нет глобального объекта location
, и он реактивный, поэтому за его изменением можно следить.
Параметры маршрута
useLocation()
извлекает параметры маршрута в объект params
.
Предположим, что у вас есть:
- Файл:
src/routes/sku/[skuId]/index.tsx
; - Пользователь переходит к:
https://example.com/sku/1234
; - Затем
skuId
можно получить черезuseLocation().params.skuId
.
import { component$ } from '@builder.io/qwik';
import { useLocation } from '@builder.io/qwik-city';
export default component$(() => {
const loc = useLocation();
return (
<>
<h1>Артикул</h1>
{loc.isNavigating && <p>Загрузка...</p>}
<p>Путь: {loc.url.pathname}</p>
<p>Код: {loc.params.skuId}</p>
</>
);
});
Приведённый выше код будет генерировать:
<h1>Артикул</h1>
<p>Путь: /sku/1234/</p>
<p>Код: 1234</p>
Обратите внимание, что
useLocation
- это API только для чтения, вы никогда не должны пытаться изменить значения возвращаемого объектаloc
. Вместо этого обратитесь к APIuseNavigate()
.
useNavigate()
Функция useNavigate()
позволяет программно переходить на следующую страницу, не требуя вмешательства пользователя и не вызывая перезагрузки всей страницы. Это API, используемый внутри компонента <Link>
для поддержки навигации SPA.
Эта функция возвращает функцию nav()
, которая может быть использована для "добавления" нового пути.
Также useNavigate
можно использовать для SPA-обновления текущей страницы, вызывая функцию nav()
без аргументов.
import { component$ } from '@builder.io/qwik';
import { useNavigate } from '@builder.io/qwik-city';
export default component$(() => {
const nav = useNavigate();
return (
<>
<button
onClick$={async () => {
// SPA-навигация к `/dashboard`
await nav('/dashboard');
}}
>
Перейти к информационной панели
</button>
<button
onClick$={async() => {
// обновление страницы: вызов без аргументов
await nav();
}}
>
Обновить страницу
</button>
</>
);
});
Этот компонент будет содержать кнопку, при нажатии на которую QwikCity будет переходить к /dashboard
без перезагрузки страницы.
Обратите внимание, что для SEO и улучшения доступности лучше использовать компонент
<Link>
вместоuseNavigate()
для перехода на новую страницу после пользовательского взаимодействия.
routeLoader$()
Функция routeLoader$()
используется для объявления нового серверного загрузчика для заданной страницы/конечной точки или макета. Qwik City выполнит все объявленные загрузчики для заданного маршрута. Компоненты Qwik могут позже ссылаться на загрузчики, импортируя их и вызывая возвращаемую пользовательскую функцию для получения данных.
import { component$ } from '@builder.io/qwik';
import { routeLoader$ } from '@builder.io/qwik-city';
export const useGetTime = routeLoader$(async () => {
return { time: new Date() }
});
export default component$(() => {
const signal = useGetTime(); // Signal<{time: Date}>
console.log('Date': signal.value.time);
return (
<div>{signal.value.time.toISOString()}</div>
)
});
Для получения дополнительной информации обратитесь к разделу Загрузчики маршрута.
routeAction$()
Функция routeAction$()
используется для объявления нового серверного действия на данной странице/конечной точке или макете. QwikCity будет выполнять только вызванное после некоторого взаимодействия с пользователем действие (например, нажатие кнопки или отправка формы).
Для получения дополнительной информации обратитесь к разделу Действия сервера.
<QwikCityProvider>
Компонент QwikCityProvider
инициализирует QwikCity в существующем документе, предоставляя необходимый контекст для работы QwikCity, такой как useContent()
и useLocation()
.
Этот компонент обычно находится в самом корне вашего приложения, в большинстве интеграций вы найдёте его в файле src/root.tsx
:
export default component$(() => {
/**
* Корень сайта QwikCity всегда начинается с компонента <QwikCityProvider>,
* сразу за ним следуют <head> и <body> документа.
*
* Не удаляйте элементы `<head>` и `<body>`.
*/
return (
<QwikCityProvider>
<head>
<meta charSet="utf-8" />
<link rel="manifest" href="/manifest.json" />
<RouterHead />
</head>
<body lang="en">
<RouterOutlet />
<ServiceWorkerRegister />
</body>
</QwikCityProvider>
);
});
QwikCityProvider
не рендерит ни один элемент DOM, даже не совпадающий маршрут, он просто инициализирует логику ядра Qwik City, по этой причине его не следует использовать более одного раза в одном и том же приложении.
<QwikCityMockProvider>
Компонент QwikCityMockProvider
инициализирует контекст Qwik City для тестирования. Он обеспечивает необходимый контекст для работы кода Qwik City в тестах, например useContent()
. И наоборот, для useNavigate()
, <Link>
, useLocation()
и так далее.
Рекомендуется использовать его в тестовых файлах.
QwikCityMockProvider
не отображает никаких элементов DOM, что означает, что он не будет виден в снэпшотах.
Если вы ищете общий пример того, как интегрировать vitest в ваш Qwik, посмотрите документацию по интеграции vitest.
import { createDOM } from '@builder.io/qwik/testing';
import { QwikCityMockProvider } from '@builder.io/qwik-city';
import { test, expect } from 'vitest';
// Компонент с двумя свойствами. Внутри использует <Link>. Опущено для краткости.
import { Card } from './card';
const cases = [
{text: 'qwik', link:'https://qwik.builder.io/docs/api'},
{text: 'vitest', link: 'https://vitest.dev'}
];
test.each(cases)('должен отрисовывать карту с %s %s', async ({text, link}) => {
const { screen, render } = await createDOM();
await render(
<QwikCityMockProvider>
<Card text={text} link={link} />
</QwikCityMockProvider>,
);
expect(screen.innerHTML).toMatchSnapshot();
});
<RouterOutlet>
Компонент RouterOutlet
отвечает за рендер совпадающего в данный момент маршрута, он использует под капотом useContent()
для отрисовки текущей страницы, а также всех вложенных макетов.
Этот компонент обычно располагается как дочерний компонент <body>
, в большинстве стартовых шаблонов вы найдёте его в файле src/root.tsx
(см. пример в QwikCityProvider
).
<Form>
Компонент Form
является обёрткой нативного элемента <form>
и предназначен для работы с серверными действиями.
Поскольку этот компонент использует нативный элемент <form>
, он будет работать в любом браузере с включенным JavaScript и без него. Кроме того, он расширяет нативный элемент <form>
, перехватывая событие submit
и предотвращая поведение по умолчанию, поэтому он будет вести себя как SPA (Single Page Application) вместо вызова полной перезагрузки страницы.
import { component$ } from '@builder.io/qwik';
import { Form, action$ } from '@builder.io/qwik-city';
// это действие будет вызвано при отправке формы
export const useLoginAction = routeAction$((data, { cookies, redirect }) => {
if (validate(data.username, data.password)) {
cookies.set('auth', getAuthToken(data.username));
throw redirect(302, '/dashboard');
}
});
export default component$(() => {
const login = useLoginAction();
return (
<Form action={login}>
<input type="text" name="username" />
<input type="password" name="password" />
<button type="submit">Войти</button>
</Form>
);
});
<Link>
Компонент Link
работает как элемент якоря <a>
, но вместо того, чтобы вызывать перезагрузку всей страницы, он осуществляет навигацию как SPA (Single Page Navigation). Это полезно, если вам нужно перемещаться без потери текущего состояния.
Помните, что полная перезагрузка страницы в Qwik чрезвычайно дёшева, другие фреймворки злоупотребляют ссылками SPA, потому что перезагрузка полной страницы требует от JS гидратации и выполнения заново. В случае с Qwik дело обстоит иначе. В ходе внутреннего тестирования мы обнаружили, что использование
<a>
обычно приводит к наиболее быстрому взаимодействию.
Под капотом компонент <Link>
использует API useNavigate()
и предотвращает поведение по умолчанию встроенного <a>
:
import { component$ } from '@builder.io/qwik';
import { useNavigate } from '@builder.io/qwik-city';
export const Link = component$<LinkProps>((props) => {
const nav = useNavigate();
return (
<a
preventdefault:click
onClick$={() => {
nav(props.href);
}}
{...props}
>
<Slot />
</a>
);
});
Использование
import { component$ } from '@builder.io/qwik';
import { Link } from '@builder.io/qwik-city';
export default component$(() => {
return (
<div>
<a href="/docs" class="my-link">
Полная перезагрузка страницы
</a>
<Link href="/docs" class="my-link">
SPA-навигация
</Link>
</div>
);
});