Skip to main content

Docusaurus 客户端 API

Docusaurus 提供了一组客户端 API,对于构建网站很有帮助。

组件

<ErrorBoundary />

This component creates a React error boundary.

Use it to wrap components that might throw, and display a fallback when that happens instead of crashing the whole app.

import React from 'react';
import ErrorBoundary from '@docusaurus/ErrorBoundary';

const SafeComponent = () => (
<ErrorBoundary
fallback={({error, tryAgain}) => (
<div>
<p>This component crashed because of error: {error.message}.</p>
<button onClick={tryAgain}>Try Again!</button>
</div>
)}>
<SomeDangerousComponentThatMayThrow />
</ErrorBoundary>
);
tip

To see it in action, click here:

info

Docusaurus uses this component to catch errors within the theme's layout, and also within the entire app.

note

This component doesn't catch build-time errors, and only protects against client-side render errors that can happen when using stateful React components.

Props

  • fallback: an optional callback returning a JSX element. It will receive two props: error, the error that was caught, and tryAgain, a function (() => void) callback to reset the error in the component and try rendering it again.

这是一个可重用 React 组件,用于管理对 HTML 文档标头(即 <head> 中的标签)的修改。此组件接收纯 HTML 标签并输出纯 HTML 标签,对初学者很友好。此组件始对 React Helmet 的二次包装。

用法示例:

import React from 'react';
import Head from '@docusaurus/Head';

const MySEO = () => (
<Head>
<meta property="og:description" content="My custom description" />
<meta charSet="utf-8" />
<title>My Title</title>
<link rel="canonical" href="http://mysite.com/example" />
</Head>
);

嵌套或靠后定义的组件将覆盖之前的定义:

<Parent>
<Head>
<title>My Title</title>
<meta name="description" content="Helmet application" />
</Head>
<Child>
<Head>
<title>Nested Title</title>
<meta name="description" content="Nested component" />
</Head>
</Child>
</Parent>

输出为:

<head>
<title>Nested Title</title>
<meta name="description" content="Nested component" />
</head>

此组件让你可以链接站内页面并使用被称为预加载(preloading)的强大功能。预加载功能用于预取资源,以便在用户使用此组件切换页面时取回页面资源。我们利用 IntersectionObserver 检测到<Link> 处于视口(viewport)中时发起一个低优先级的资源请求,并且利用 onMouseOver 事件来发起一个高优先级的资源请求(因为这是用户的明确目的)。

此组件是对 react-router 的 <Link> 组件的二次包装,并添加了专门对 Docusaurus 的增强功能。所有传递过来的参数(props)都将透传给 react-router 的 <Link> 组件。

可用于指向站外的链接,并且会被自动添加这些属性:target="_blank" rel="noopener noreferrer"

import React from 'react';
import Link from '@docusaurus/Link';

const Page = () => (
<div>
<p>
Check out my <Link to="/blog">blog</Link>!
</p>
<p>
Follow me on <Link to="https://twitter.com/docusaurus">Twitter</Link>
</p>
</div>
);

to:字符串类型

目标位置。例如: /docs/introduction

<Link to="/courses" />

<Redirect/>

<Redirect> 渲染之后用于导航到新位置。新位置将覆盖 history 记录栈中的当前位置,就像服务器端的重定向(即 HTTP 3xx)一样。你可以参考 React Router 中关于重定向的文档 以了解有哪些参数(props)可以使用。

用法示例:

import React from 'react';
import {Redirect} from '@docusaurus/router';

const Home = () => {
return <Redirect to="/docs/test" />;
};
note

@docusaurus/router 实现了 React Router 并支持同样功能。

<BrowserOnly/>

<BrowserOnly> 组件只允许在浏览器中渲染 React 组件,并且是在 React 应用程序运行(hydrated)之后。

tip

Use it for integrating with code that can't run in Node.js, because window or document objects are being accessed.

Props

  • children: render function prop returning browser-only JSX. Will not be executed in Node.js
  • fallback (optional): JSX to render on the server (Node.js) and until React hydration completes.

Example with code

import BrowserOnly from '@docusaurus/BrowserOnly';

const MyComponent = () => {
return (
<BrowserOnly>
{() => <span>page url = {window.location.href}</span>}
</BrowserOnly>
);
};

Example with a library

import BrowserOnly from '@docusaurus/BrowserOnly';

const MyComponent = (props) => {
return (
<BrowserOnly fallback={<div>Loading...</div>}>
{() => {
const LibComponent = require('some-lib').LibComponent;
return <LibComponent {...props} />;
}}
</BrowserOnly>
);
};

<Interpolate/>

该组件用于对文本中所包含的占位符做替换。

占位符将被替换为动态值和你所选择的 JSX 元素(字符串、链接、styled elements等)。

参数(Props)

  • children:包含占位符(例如 {placeholderName})的文本
  • values:包含占位符替换值的对象
import React from 'react';
import Link from '@docusaurus/Link';
import Interpolate from '@docusaurus/Interpolate';

export default function VisitMyWebsiteMessage() {
return (
<Interpolate
values={{
firstName: 'Sébastien',
website: (
<Link to="https://docusaurus.io" className="my-website-class">
website
</Link>
),
}}>
{'Hello, {firstName}! How are you? Take a look at my {website}'}
</Interpolate>
);
}

<Translate/>

本地化你的网站 时,<Translate/> 组件将用于 为 React 组件提供对翻译功能的支持,例如翻译你的主页。<Translate> 组件支持 interpolation

待翻译的字符串将被 docusaurus write-translations 命令从你的代码中提取出来,并在 website/i18n/<locale> 位置创建一个 code.json 文件用于翻译。

note

<Translate/> 组件的参数(props)只能是硬编码的字符串

除了用于 interpolation 的 values 参数(prop)外,不能使用变量,否则无法提取待翻译的字符串。

参数(Props)

  • children:网站的默认 locale 中未经翻译的字符串(可以包含 用于被替换的占位符
  • id:可选值,在 JSON 文件(保存待翻译的字符串)中作为键(key)使用
  • description:可选值,用于为译者提供帮助性的信息
  • values: 可选值,该对象包含用于替换占位符的值

示例

src/pages/index.js
import React from 'react';
import Layout from '@theme/Layout';

import Translate from '@docusaurus/Translate';

export default function Home() {
return (
<Layout>
<h1>
<Translate
id="homepage.title"
description="The homepage welcome message">
Welcome to my website
</Translate>
</h1>
<main>
<Translate values={{firstName: 'Sébastien'}}>
{'Welcome, {firstName}! How are you?'}
</Translate>
</main>
</Layout>
);
}
note

You can even omit a children prop and specify a translation string in your code.json file manually after running the docusaurus write-translations CLI command.

<Translate id="homepage.title" />

React 钩子(Hooks)

useDocusaurusContext

用于访问 Docusaurus 核心数据的 React 钩子(hook)。核心数据包含来自 docusaurus.config.js 中的 siteConfig 对象,以及一些其它的站点元数据信息。

type DocusaurusPluginVersionInformation =
| {readonly type: 'package'; readonly version?: string}
| {readonly type: 'project'}
| {readonly type: 'local'}
| {readonly type: 'synthetic'};

interface DocusaurusSiteMetadata {
readonly docusaurusVersion: string;
readonly siteVersion?: string;
readonly pluginVersions: Record<string, DocusaurusPluginVersionInformation>;
}

interface I18nLocaleConfig {
label: string;
direction: string;
}

interface I18n {
defaultLocale: string;
locales: [string, ...string[]];
currentLocale: string;
localeConfigs: Record<string, I18nLocaleConfig>;
}

interface DocusaurusContext {
siteConfig: DocusaurusConfig;
siteMetadata: DocusaurusSiteMetadata;
globalData: Record<string, unknown>;
i18n: I18n;
codeTranslations: Record<string, string>;
}

用法示例:

import React from 'react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';

const MyComponent = () => {
const {siteConfig, siteMetadata} = useDocusaurusContext();
return (
<div>
<h1>{siteConfig.title}</h1>
<div>{siteMetadata.siteVersion}</div>
<div>{siteMetadata.docusaurusVersion}</div>
</div>
);
};

useIsBrowser

Returns true when the React app has successfully hydrated in the browser.

caution

Use this hook instead of typeof windows !== 'undefined' in React rendering logic.

The first client-side render output (in the browser) must be exactly the same as the server-side render output (Node.js).

Not following this rule can lead to unexpected hydration behaviors, as described in The Perils of Rehydration.

Usage example:

import React from 'react';
import useIsBrowser from '@docusaurus/useIsBrowser';

const MyComponent = () => {
const isBrowser = useIsBrowser();
return <div>{isBrowser ? 'Client' : 'Server'}</div>;
};

useBaseUrl

此 React 钩子(hook)用于将网站的 baseUrl 添加到某个字符串前面。

caution

请勿将其用于普通链接!

默认情况下,/baseUrl/ 前缀会被自动添加到所有 绝对路径 前面:

  • Markdown:[link](/my/path) 将连接到 /baseUrl/my/path
  • React: <Link to="/my/path/">link</Link> 将连接到 /baseUrl/my/path

参数

type BaseUrlOptions = {
forcePrependBaseUrl: boolean;
absolute: boolean;
};

用法示例:

import React from 'react';
import useBaseUrl from '@docusaurus/useBaseUrl';

const SomeImage = () => {
const imgSrc = useBaseUrl('/img/myImage.png');
return <img src={imgSrc} />;
};
tip

在大多数情况下,你并不需要使用 useBaseUrl

针对 静态资源 的引用,推荐使用 require()

<img src={require('@site/static/img/myImage.png').default} />

useBaseUrlUtils

有时,useBaseUrl 还不够好用。而 useBaseUrlUtils 能够返回一组额外的与网站的 baseUrl 相关的辅助函数。

  • withBaseUrl:如果你需要一次性将 baseUrl 添加到多个网址,那么这个函数就很有用了。
import React from 'react';
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';

const Component = () => {
const urls = ['/a', '/b'];
const {withBaseUrl} = useBaseUrlUtils();
const urlsWithBaseUrl = urls.map(withBaseUrl);
return <div>{/* ... */}</div>;
};

useGlobalData

此 React 钩子(hook)用于访问所有插件所创建的全局数据。

全局数据是采用插件名和插件 id 作为命名空间的。

info

当一个站点上使用某个插件的多个实例时,插件 id 才有用。每个插件实例都可以创建自己的全局数据。

type GlobalData = Record<
PluginName,
Record<
PluginId, // 默认值是 "default"
any // 特定于插件的数据
>
>;

用法示例:

import React from 'react';
import useGlobalData from '@docusaurus/useGlobalData';

const MyComponent = () => {
const globalData = useGlobalData();
const myPluginData = globalData['my-plugin']['default'];
return <div>{myPluginData.someAttribute}</div>;
};
tip

通过 ./docusaurus/globalData.json 文件可以查看站点的全局数据

usePluginData

访问由特定插件实例所创建的全局数据。

这是一个访问插件的全局数据的最方便的 React 钩子(hook),大部分情况下都应该使用它。

如果你没有使用插件的多个实例,则 pluginId 是可选的。

usePluginData(pluginName: string, pluginId?: string)

用法示例:

import React from 'react';
import {usePluginData} from '@docusaurus/useGlobalData';

const MyComponent = () => {
const myPluginData = usePluginData('my-plugin');
return <div>{myPluginData.someAttribute}</div>;
};

useAllPluginInstancesData

访问由特定插件所创建的全局数据。给定插件名称后,该函数将返回以该名称命名的所有插件实例的全局数据,并按照插件 id 标记数据。

useAllPluginInstancesData(pluginName: string)

用法示例:

import React from 'react';
import {useAllPluginInstancesData} from '@docusaurus/useGlobalData';

const MyComponent = () => {
const allPluginInstancesData = useAllPluginInstancesData('my-plugin');
const myPluginData = allPluginInstancesData['default'];
return <div>{myPluginData.someAttribute}</div>;
};

函数

interpolate

对应 <Interpolate> 组件的具有相同功能的函数。

用法

// 简单的字符串替换
function interpolate(text: string, values: Record<string, string>): string;

// JSX interpolation
function interpolate(
text: string,
values: Record<string, ReactNode>,
): ReactNode;

示例

import {interpolate} from '@docusaurus/Interpolate';

const message = interpolate('Welcome {firstName}', {firstName: 'Sébastien'});

translate

对应 <Translate> 组件的具有相同功能的函数。也支持 占位符替换

tip

对于 无法使用组件罕见情况,请使用该函数,例如:

  • 页面的 title 元数据
  • 表单输入框的 placeholder 属性(props)
  • 用于可访问性功能中的 aria-label 属性(props)

用法

function translate(
translation: {message: string; id?: string; description?: string},
values: Record<string, string>,
): string;

示例

src/pages/index.js
import React from 'react';
import Layout from '@theme/Layout';

import {translate} from '@docusaurus/Translate';

export default function Home() {
return (
<Layout
title={translate({message: 'My page meta title'})}
>
<img
src={'https://docusaurus.io/logo.png'}
aria-label={
translate(
{
message: 'The logo of site {siteName}',
// 可选
id: 'homepage.logo.ariaLabel',
description: 'The home page logo aria label',
},
{siteName: 'Docusaurus'},
)
}
/>
</Layout>
);
}

模块

ExecutionEnvironment

该模块用于暴露一些用于检查当前渲染环境的布尔值变量。

caution

For React rendering logic, use useIsBrowser() or <BrowserOnly> instead.

Example:

import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';

if (ExecutionEnvironment.canUseDOM) {
require('lib-that-only-works-client-side');
}
变量描述
ExecutionEnvironment.canUseDOM如果在客户端或浏览器中,则为 true;如果是在 Node.js 或预渲染阶段,则为 false
ExecutionEnvironment.canUseEventListeners如果在客户端并且定义了 window.addEventListener,则为true
ExecutionEnvironment.canUseIntersectionObserver如果在客户端并且定义了 IntersectionObserver,则为 true
ExecutionEnvironment.canUseViewport如果在客户端并且定义了 window.screen,则为true

constants

该模块用于为客户端的主题代码暴露一些有用的常量。

import {DEFAULT_PLUGIN_ID} from '@docusaurus/constants';
Named exportValue
DEFAULT_PLUGIN_IDdefault