Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 47 additions & 32 deletions src/content/docs/zh-cn/guides/view-transitions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Steps } from '@astrojs/starlight/components'

Astro 仅需几行代码就可以支持**可选择的,每个页面的视图过渡动画**。视图过渡动画可以在不刷新浏览器的情况下更新页面内容,并在页面之间提供无缝的动画效果。

Astro 提供了一个 `<ViewTransitions />` 路由组件,可以添加到单个页面的 `<head>` 中,以控制页面在导航到另一个页面时的过渡效果。它提供了一个轻量级的客户端路由器,[拦截导航](#客户端导航流程) 并允许你自定义页面之间的过渡效果。
Astro 提供了一个 `<ClientRouter />` 路由组件,可以添加到单个页面的 `<head>` 中,以控制页面在导航到另一个页面时的过渡效果。它提供了一个轻量级的客户端路由器,[拦截导航](#客户端导航流程) 并允许你自定义页面之间的过渡效果。

将此组件添加到一个可复用的 `.astro` 组件中,例如公共头部或布局组件,以便 [在整个站点上实现动画页面过渡(SPA 模式)](#整站视图过渡动画spa-模式)。

Expand All @@ -30,16 +30,16 @@ Astro 的视图过渡动画支持由新的 [View Transitions](https://developer.

## 向页面添加视图过渡动画

通过在每个页面的 `<head>` 中导入和添加 `<ViewTransitions />` 路由组件,可以选择在单个页面上使用视图过渡动画。
通过在每个页面的 `<head>` 中导入和添加 `<ClientRouter />` 路由组件,可以选择在单个页面上使用视图过渡动画。

```astro title="src/pages/index.astro" ins={2,7}
---
import { ViewTransitions } from 'astro:transitions';
import { ClientRouter } from 'astro:transitions';
---
<html lang="en">
<head>
<title>我的主页</title>
<ViewTransitions />
<ClientRouter />
</head>
<body>
<h1>欢迎来到我的网站!</h1>
Expand All @@ -49,13 +49,13 @@ import { ViewTransitions } from 'astro:transitions';

## 整站视图过渡动画(SPA 模式)

导入 `<ViewTransitions />` 组件并将其添加到公共 `<head>` 或共享布局组件中。Astro 将根据旧页面和新页面之间的相似之处创建默认的页面动画,并为不支持的浏览器提供回退行为。
导入 `<ClientRouter />` 组件并将其添加到公共 `<head>` 或共享布局组件中。Astro 将根据旧页面和新页面之间的相似之处创建默认的页面动画,并为不支持的浏览器提供回退行为。

下面的示例显示了如何通过导入和添加此组件到 `<CommonHead />` Astro 组件中,为不支持的浏览器提供默认的页面导航动画,包括默认的回退控制选项,从而在整个站点上添加 Astro 的默认页面导航动画:

```astro title="src/components/CommonHead.astro" ins={2,12}
---
import { ViewTransitions } from 'astro:transitions';
import { ClientRouter } from 'astro:transitions';
---
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
Expand All @@ -65,7 +65,7 @@ import { ViewTransitions } from 'astro:transitions';
<meta name="title" content={title} />
<meta name="description" content={description} />

<ViewTransitions />
<ClientRouter />
```

无需其他配置即可启用 Astro 的默认客户端导航!
Expand Down Expand Up @@ -224,11 +224,11 @@ export interface TransitionDirectionalAnimations {

```astro title="src/layouts/Layout.astro"
---
import { ViewTransitions } from 'astro:transitions';
import { ClientRouter } from 'astro:transitions';
---
<html lang="en">
<head>
<ViewTransitions />
<ClientRouter />
</head>
<body>
<slot />
Expand Down Expand Up @@ -281,7 +281,7 @@ const customTransition = {

## 路由器控制

`<ViewTransitions />` 路由器通过监听以下事件来处理导航:
`<ClientRouter />` 路由器通过监听以下事件来处理导航:

- 点击 `<a>` 元素。
- 后退和前进导航事件。
Expand All @@ -294,9 +294,9 @@ const customTransition = {

### 阻止客户端导航

只有关联的两个页面都使用了 `<ViewTransitions />` 路由器才能通过客户端路由进行导航,防止重新加载全页面。你可能也不希望在每次导航更改时都使用客户端路由,而是更希望在特定路由上进行传统的页面导航。
只有关联的两个页面都使用了 `<ClientRouter />` 路由器才能通过客户端路由进行导航,防止重新加载全页面。你可能也不希望在每次导航更改时都使用客户端路由,而是更希望在特定路由上进行传统的页面导航。

你可以通过将 `data-astro-reload` 属性添加到任何 `<a>` 或 `<form>` 标签中,为单个链接选择不使用客户端路由器。此属性将覆盖任何现有的 `<ViewTransitions />` 组件,而是在导航期间触发浏览器刷新。
你可以通过将 `data-astro-reload` 属性添加到任何 `<a>` 或 `<form>` 标签中,为单个链接选择不使用客户端路由器。此属性将覆盖任何现有的 `<ClientRouter />` 组件,而是在导航期间触发浏览器刷新。

以下示例显示了仅从主页导航到文章时如何阻止客户端路由器。这样,当从文章列表页面导航到同一页面时,仍然可以对共享元素(例如主视觉图)进行动画处理:

Expand All @@ -312,7 +312,7 @@ const customTransition = {

### 触发导航

你还可以使用 `navigate` 方法在通常不被 `<ViewTransitions />` 路由器监听的事件里触发客户端导航。该函数来自于 `astro:transitions/client` 模块,可以在任何客户端脚本和通过[客户端指令](/zh-cn/reference/directives-reference/#客户端指令)激活了的客户端组件中使用。
你还可以使用 `navigate` 方法在通常不被 `<ClientRouter />` 路由器监听的事件里触发客户端导航。该函数来自于 `astro:transitions/client` 模块,可以在任何客户端脚本和通过[客户端指令](/zh-cn/reference/directives-reference/#客户端指令)激活了的客户端组件中使用。

下面的示例展示了一个当访客选择菜单中的选项时导航到另一个页面的 Astro 组件:
```astro title="src/components/Form.astro"
Expand All @@ -334,11 +334,11 @@ const customTransition = {
```astro title="src/pages/index.astro"
---
import Form from "../components/Form.astro";
import { ViewTransitions } from "astro:transitions";
import { ClientRouter } from "astro:transitions";
---
<html>
<head>
<ViewTransitions />
<ClientRouter />
</head>
<body>
<Form />
Expand All @@ -362,16 +362,16 @@ export default function Form() {
);
}
```
这个 `<Form />` 组件可以在使用 `<ViewTransitions />` 路由器的 Astro 页面上带着客户端指令渲染:
这个 `<Form />` 组件可以在使用 `<ClientRouter />` 路由器的 Astro 页面上带着客户端指令渲染:

```astro title="src/pages/index.astro"
---
import Form from "../components/Form.jsx";
import { ViewTransitions } from "astro:transitions";
import { ClientRouter } from "astro:transitions";
---
<html>
<head>
<ViewTransitions />
<ClientRouter />
</head>
<body>
<Form client:load />
Expand All @@ -395,7 +395,7 @@ import { ViewTransitions } from "astro:transitions";

通常情况下,你每次导航时都会在浏览器的历史记录中写入一个新条目。这样可以使用浏览器的 `back` 和 `forward` 按钮在页面之间导航。

`<ViewTransitions />` 路由器器允许你通过向任何单独的 `<a>` 标签添加 `data-astro-history` 属性来覆盖历史记录条目。
`<ClientRouter />` 路由器器允许你通过向任何单独的 `<a>` 标签添加 `data-astro-history` 属性来覆盖历史记录条目。

`data-astro-history` 属性可以设置为与 [`navigate()` 函数的 `history` 选项](#触发导航) 相同的三个值:

Expand All @@ -416,7 +416,7 @@ import { ViewTransitions } from "astro:transitions";

<p><Since v="4.0.0" /></p>

`<ViewTransitions />` 路由器将从 `<form>` 元素触发页面内的转换,支持 `GET` 和 `POST` 请求。
`<ClientRouter />` 路由器将从 `<form>` 元素触发页面内的转换,支持 `GET` 和 `POST` 请求。

默认情况下,当你的 `method` 设置为 `POST` 时,Astro 会将表单数据提交为 `multipart/form-data`。如果你想要匹配浏览器的默认行为,请使用 `enctype` 属性将你的数据编码为 `application/x-www-form-urlencoded`:

Expand All @@ -436,21 +436,21 @@ import { ViewTransitions } from "astro:transitions";

## 回退控制

`<ViewTransitions />` 路由器在支持视图过渡动画的浏览器(如 Chromium 浏览器)中表现最佳,但也包含了对其他浏览器的默认回退支持。即当浏览器不支持视图过渡动画 API 时,Astro 仍将提供基于浏览器的导航,使用其中一种回退选项来实现类似的效果。
`<ClientRouter />` 路由器在支持视图过渡动画的浏览器(如 Chromium 浏览器)中表现最佳,但也包含了对其他浏览器的默认回退支持。即当浏览器不支持视图过渡动画 API 时,Astro 仍将提供基于浏览器的导航,使用其中一种回退选项来实现类似的效果。

你可以通过在 `<ViewTransitions />` 组件上添加一个名为 `fallback` 的属性,并将其设置为 `swap` 或 `none`,来覆盖 Astro 的默认回退支持:
你可以通过在 `<ClientRouter />` 组件上添加一个名为 `fallback` 的属性,并将其设置为 `swap` 或 `none`,来覆盖 Astro 的默认回退支持:

- `animate`(默认,推荐使用)- Astro 将在更新页面内容之前使用自定义属性模拟视图过渡动画。
- `swap` - Astro 不会尝试进行页面动画效果。相反,旧页面将立即被新页面替换。
- `none` - Astro 将不进行任何页面过渡动画。在不支持的浏览器中,你将获得全量的页面导航。

```astro
---
import { ViewTransitions } from 'astro:transitions';
import { ClientRouter } from 'astro:transitions';
---
<title>My site</title>

<ViewTransitions fallback="swap" />
<ClientRouter fallback="swap" />
```

:::note[已知限制]
Expand All @@ -459,7 +459,7 @@ Astro 不会模拟 `initial` 浏览器动画。因此,任何使用此动画的

## 客户端导航流程

当 `<ViewTransitions />` 路由器被使用时,以下步骤将会产生 Astro 的客户端导航:
当 `<ClientRouter />` 路由器被使用时,以下步骤将会产生 Astro 的客户端导航:

<Steps>
1. 一个访客通过以下任何操作触发导航:
Expand Down Expand Up @@ -495,7 +495,7 @@ Astro 不会模拟 `initial` 浏览器动画。因此,任何使用此动画的

### 脚本顺序

在使用 `<ViewTransitions />` 组件导航页面时,脚本将按顺序运行以匹配浏览器行为。
在使用 `<ClientRouter />` 组件导航页面时,脚本将按顺序运行以匹配浏览器行为。


### 脚本的重新执行
Expand All @@ -506,6 +506,8 @@ Astro 不会模拟 `initial` 浏览器动画。因此,任何使用此动画的

通过视图过渡,某些脚本可能不再像浏览器整页刷新那样,在页面导航后重新运行。你可以监听多个 [客户端路由期间的事件](#生命周期事件),并在事件发生时触发事件。你可以将现有脚本包装在事件监听器中,以确保它在导航周期中的正确时间运行。

以下示例将一个会动的 "汉堡" 菜单的脚本包装在了 `astro:page-load` 的事件监听器中,该事件监听器在页面导航结束时运行,以使菜单响应导航到新页面后的点击:

```js title="src/scripts/menu.js" ins={2,6}
<script>
document.addEventListener('astro:page-load', () => {
Expand All @@ -516,6 +518,20 @@ document.addEventListener('astro:page-load', () => {
</script>
```

以下示例展示了一个响应 `astro:after-swap` 事件来运行的函数,该事件在新页面替换旧页面之后、DOM 元素绘制到屏幕之前立即触发。该示例通过在渲染新页面之前检查并设置暗色主题(如果有需要的话),来避免页面导航到亮色主题后出现屏闪的问题:

```astro title="src/components/ThemeToggle.astro"
<script is:inline>
function applyTheme() {
localStorage.theme === 'dark'
? document.documentElement.classList.add("dark")
: document.documentElement.classList.remove("dark");
}
document.addEventListener('astro:after-swap', applyTheme);
applyTheme();
</script>
```

#### `data-astro-rerun`

<p><Since v="4.5.0" /></p>
Expand All @@ -530,7 +546,6 @@ document.addEventListener('astro:page-load', () => {

如果你有在内联脚本中设置了全局状态的代码,那么这个状态需要考虑到脚本可能会被执行多次的情况。在你的 `<script>` 标签中检查全局状态,并在可能的情况下有条件地执行你的代码。这是因为 `window` 对象是被保留的。


```astro
<script is:inline>
if (!window.SomeGlobal) {
Expand All @@ -541,7 +556,7 @@ document.addEventListener('astro:page-load', () => {

## 生命周期事件

`<ViewTransition />` 路由器在导航期间在 `document` 上触发了许多事件。这些事件提供了导航生命周期的钩子,允许你做一些事情,例如显示新页面正在加载的指示器、覆盖默认行为以及在导航完成时恢复状态。
`<ClientRouter />` 路由器在导航期间在 `document` 上触发了许多事件。这些事件提供了导航生命周期的钩子,允许你做一些事情,例如显示新页面正在加载的指示器、覆盖默认行为以及在导航完成时恢复状态。

导航过程包括一个**准备**阶段,在此阶段加载新内容;一个**DOM 交换**阶段,在此阶段旧页面的内容被新页面的内容替换;以及一个**完成**阶段,在此阶段执行脚本,报告加载完成,并进行清理工作。

Expand Down Expand Up @@ -692,7 +707,7 @@ document.addEventListener('astro:after-swap',

在页面导航结束时触发的事件,在新页面对用户可见且阻塞样式和脚本加载完成后。你可以在 `document` 上监听此事件。

`<ViewTransitions />` 组件在预渲染页面的初始页面导航以及任何后续导航(向前或向后)时都会触发此事件。
`<ClientRouter />` 组件在预渲染页面的初始页面导航以及任何后续导航(向前或向后)时都会触发此事件。

你可以使用此事件在每次页面导航时运行代码,或者只运行一次:

Expand All @@ -713,9 +728,9 @@ document.addEventListener('astro:after-swap',

<p><Since v="3.2.0" /></p>

`<ViewTransitions />` 组件包含一个用于在客户端路由间进行页面导航的路由读出器。你无需配置或操作即可启用此功能。
`<ClientRouter />` 组件包含一个用于在客户端路由间进行页面导航的路由读出器。你无需配置或操作即可启用此功能。

辅助技术通过在导航后读出新页面标题来告知访客页面已被更改。在使用传统的全页面浏览器刷新服务端路由时,则会默认在新页面加载后执行此操作。而在客户端路由中,则由 `<ViewTransitions />` 组件执行此操作。
辅助技术通过在导航后读出新页面标题来告知访客页面已被更改。在使用传统的全页面浏览器刷新服务端路由时,则会默认在新页面加载后执行此操作。而在客户端路由中,则由 `<ClientRouter />` 组件执行此操作。

为在客户端路由中添加路由读出,该组件会向新页面添加一个带有 `aria-live` 属性设置为 `assertive` 的元素。这告诉 AT(assistive technology,辅助技术)立即读出。该组件还按照优先顺序检查以下内容来确定读出的文本:

Expand All @@ -727,4 +742,4 @@ document.addEventListener('astro:after-swap',

### `prefers-reduced-motion`

Astro 的 `<ViewTransitions />` 组件包含一个 CSS 媒体查询,当检测到 [`prefer-reduced-motion`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/@media/prefers-reduced-motion) 设置时,禁用所有视图过渡动画,包括回退动画。相反,浏览器将不使用动画,简单直接的切换 DOM 元素。
Astro 的 `<ClientRouter />` 组件包含一个 CSS 媒体查询,当检测到 [`prefer-reduced-motion`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/@media/prefers-reduced-motion) 设置时,禁用所有视图过渡动画,包括回退动画。相反,浏览器将不使用动画,简单直接的切换 DOM 元素。