Skip to content

查看转场

Astro 仅需几行代码即可支持选择加入、每页、视图转换。视图转换无需浏览器正常的全页导航刷新即可更新页面内容,并在页面之间提供无缝动画。

¥Astro supports opt-in, per-page, view transitions with just a few lines of code. View transitions update your page content without the browser’s normal, full-page navigation refresh and provide seamless animations between pages.

Astro 提供了 <ViewTransitions /> 路由组件,可以将其添加到单个页面的 <head> 中,以在你导航到另一个页面时控制页面转换。它提供了 拦截导航 的轻量级客户端路由,并允许你自定义页面之间的转换。

¥Astro provides a <ViewTransitions /> routing component that can be added to a single page’s <head> to control page transitions as you navigate away to another page. It provides a lightweight client-side router that intercepts navigation and allows you to customize the transition between pages.

将此组件添加到可重用的 .astro 组件中,例如 整个网站的动画页面转换(SPA 模式) 的公共头或布局。

¥Add this component to a reusable .astro component, such as a common head or layout, for animated page transitions across your entire site (SPA mode).

Astro 的视图转换支持由新的 查看转场 浏览器 API 提供支持,还包括:

¥Astro’s view transitions support is powered by the new View Transitions browser API and also includes:

¥Adding View Transitions to a Page

通过将 <ViewTransitions /> 路由组件导入并添加到每个所需页面上的 <head>,选择在各个页面上使用视图转换。

¥Opt in to using view transitions on individual pages by importing and adding the <ViewTransitions /> routing component to <head> on every desired page.

src/pages/index.astro
---
import { ViewTransitions } from 'astro:transitions';
---
<html lang="en">
<head>
<title>My Homepage</title>
<ViewTransitions />
</head>
<body>
<h1>Welcome to my website!</h1>
</body>
</html>

完整站点视图转换(SPA 模式)

Section titled 完整站点视图转换(SPA 模式)

¥Full site view transitions (SPA mode)

<ViewTransitions /> 组件导入并添加到常见的 <head> 或共享布局组件中。Astro 将根据新旧页面之间的相似性创建默认页面动画,并且还将为不受支持的浏览器提供后备行为。

¥Import and add the <ViewTransitions /> component to your common <head> or shared layout component. Astro will create default page animations based on the similarities between the old and new page, and will also provide fallback behavior for unsupported browsers.

下面的示例显示了通过将此组件导入并添加到 <CommonHead /> Astro 组件,在整个站点范围内添加 Astro 的默认页面导航动画,包括不支持的浏览器的默认回退控制选项:

¥The example below shows adding Astro’s default page navigation animations site-wide, including the default fallback control option for non-supporting browsers, by importing and adding this component to a <CommonHead /> Astro component:

src/components/CommonHead.astro
---
import { ViewTransitions } from 'astro:transitions';
---
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<!-- Primary Meta Tags -->
<title>{title}</title>
<meta name="title" content={title} />
<meta name="description" content={description} />
<ViewTransitions />

无需其他配置即可启用 Astro 的默认客户端导航!

¥No other configuration is necessary to enable Astro’s default client-side navigation!

在单个元素上使用 转场指令覆盖默认的客户端导航 可以进行更精细的控制。

¥Use transition directives or override default client-side navigation on individual elements for finer control.

¥Transition Directives

Astro 会自动为旧页面和新页面中找到的相应元素分配一个共享的、唯一的 view-transition-name。这对匹配元素是通过元素的类型及其在 DOM 中的位置来推断的。

¥Astro will automatically assign corresponding elements found in both the old page and the new page a shared, unique view-transition-name. This pair of matching elements is inferred by both the type of element and its location in the DOM.

.astro 组件中的页面元素上使用可选的 transition:* 指令,以便更好地控制导航期间的页面转换行为。

¥Use optional transition:* directives on page elements in your .astro components for finer control over the page transition behaviour during navigation.

  • transition:name:允许你覆盖 Astro 的旧/新内容动画和 指定转换名称 的默认元素匹配以关联一对 DOM 元素。

  • transition:animate:允许你覆盖 Astro 的默认动画,同时通过指定动画类型用新元素替换旧元素。使用 Astro 的 内置动画指令创建自定义转场动画

  • transition:persist:允许你在导航到另一个页面时覆盖 Astro 的默认设置,将旧元素替换为新元素,并替换 保留组件和 HTML 元素

¥Naming a transition

在某些情况下,你可能希望或需要自己识别相应的视图转场元素。你可以使用 transition:name 指令为一对元素指定名称。

¥In some cases, you may want or need to identify the corresponding view transition elements yourself. You can specify a name for a pair of elements using the transition:name directive.

src/pages/old-page.astro
<aside transition:name="hero">
src/pages/new-page.astro
<aside transition:name="hero">

请注意,提供的 transition:name 值在每个页面上只能使用一次。当 Astro 本身无法推断出正确的名称时,或者为了对匹配元素进行更精细的控制时,请手动设置此项。

¥Note that the provided transition:name value can only be used once on each page. Set this manually when Astro can’t infer a proper name itself, or for more fine control over matching elements.

¥Maintaining State

Added in: astro@2.10.0

你可以使用 transition:persist 指令在页面导航中保留组件和 HTML 元素(而不是替换它们)。

¥You can persist components and HTML elements (instead of replacing them) across page navigations using the transition:persist directive.

例如,当你导航到包含相同视频元素的另一个页面时,以下 <video> 将继续播放。这适用于向前和向后导航。

¥For example, the following <video> will continue to play as you navigate to another page that contains the same video element. This works for both forwards and backwards navigation.

src/components/Video.astro
<video controls="" autoplay="" transition:persist>
<source src="https://ia804502.us.archive.org/33/items/GoldenGa1939_3/GoldenGa1939_3_512kb.mp4" type="video/mp4">
</video>

你还可以将该指令放在 Astro 岛(带有 client: 指令 的 UI 框架组件)上。如果该组件存在于下一页上,则将继续显示旧页面中具有当前状态的群岛,而不是用新页面中的群岛替换它。

¥You can also place the directive on an Astro island (a UI framework component with a client: directive). If that component exists on the next page, the island from the old page with its current state will continue to be displayed, instead of replacing it with the island from the new page.

在下面的例子中,在包含具有 transition:persist 属性的 <Counter /> 组件的页面之间来回导航时,组件的计数内部状态不会被重置。

¥In the example below, the component’s internal state of the count will not be reset when navigating back and forth across pages that contain the <Counter /> component with the transition:persist attribute.

components/Header.astro
<Counter client:load transition:persist initialCount={5} />

如果岛/元素位于两个页面之间的不同组件中,你也可以 手动识别对应元素

¥You can also manually identify corresponding elements if the island/element is in a different component between the two pages.

src/pages/old-page.astro
<Video controls="" autoplay="" transition:name="media-player" transition:persist />
src/pages/new-page.astro
<MyVideo controls="" autoplay="" transition:name="media-player" transition:persist />

作为一种方便的简写,transition:persist 也可以将转换名称作为值。

¥As a convenient shorthand, transition:persist can alternatively take a transition name as a value.

src/pages/index.astro
<video controls="" autoplay="" transition:persist="media-player">

Added in: astro@4.5.0

这允许你控制群岛的属性是否应在导航时保留。

¥This allows you to control whether or not an island’s props should be persisted upon navigation.

默认情况下,当你将 transition:persist 添加到群岛时,状态在导航时会保留,但你的组件将使用新属性重新渲染。例如,当组件接收特定于页面的 props(例如当前页面的 title)时,这很有用。

¥By default, when you add transition:persist to an island, the state is retained upon navigation, but your component will re-render with new props. This is useful, for example, when a component receives page-specific props such as the current page’s title.

你可以通过除了 transition:persist 之外还设置 transition:persist-props 来覆盖此行为。添加此指令将保留群岛的现有属性(不使用新值重新渲染),并保持其现有状态。

¥You can override this behavior by setting transition:persist-props in addition to transition:persist. Adding this directive will keep an island’s existing props (not re-render with new values) in addition to maintaining its existing state.

¥Built-in Animation Directives

Astro 附带了一些内置动画来覆盖默认的 fade 转场。将 transition:animate 指令添加到各个元素以自定义特定转换的行为。

¥Astro comes with a few built-in animations to override the default fade transition. Add the transition:animate directive to individual elements to customize the behavior of specific transitions.

  • fade(默认):有态度的交叉淡入淡出动画。旧内容淡出,新内容淡入。

  • initial:选择退出 Astro 有态度的交叉淡入淡出动画并使用浏览器的默认样式。

  • slide:旧内容从左侧滑出、新内容从右侧滑入的动画。在向后导航时,动画是相反的。

  • none:禁用浏览器的默认动画。在页面的 <html> 元素上使用可禁用页面上每个元素的默认淡入淡出。

组合指令以完全控制页面动画。在 <html> 元素上设置页面默认值,并根据需要覆盖任何单个元素。

¥Combine directives for full control over your page animation. Set a page default on the <html> element, and override on any individual elements as desired.

下面的示例为正文内容生成幻灯片动画,同时为页面的其余部分禁用浏览器的默认淡入淡出动画:

¥The example below produces a slide animation for the body content while disabling the browser’s default fade animation for the rest of the page:

---
import CommonHead from '../components/CommonHead.astro';
---
<html transition:animate="none">
<head>
<CommonHead />
</head>
<body>
<header>
...
</header>
<!-- Override your page default on a single element -->
<main transition:animate="slide">
...
</main>
</body>
</html>

¥Customizing Animations

你可以使用任何 CSS 动画属性自定义转场的各个方面。

¥You can customize all aspects of a transition with any CSS animation properties.

要自定义内置动画,首先从 astro:transitions 导入动画,然后传入自定义选项。

¥To customize a built-in animation, first import the animation from astro:transitions, and then pass in customization options.

下面的示例自定义内置 fade 动画的持续时间:

¥The example below customizes the duration of the built-in fade animation:

---
import { fade } from 'astro:transitions';
---
<header transition:animate={fade({ duration: '0.4s' })}>

你还可以根据以下类型,通过定义前进和后退行为以及新页面和旧页面来定义自己的动画以与 transition:animate 一起使用:

¥You can also define your own animations for use with transition:animate by defining both the forwards and backwards behavior, as well as new and old pages, according to the following types:

export interface TransitionAnimation {
name: string; // The name of the keyframe
delay?: number | string;
duration?: number | string;
easing?: string;
fillMode?: string;
direction?: string;
}
export interface TransitionAnimationPair {
old: TransitionAnimation | TransitionAnimation[];
new: TransitionAnimation | TransitionAnimation[];
}
export interface TransitionDirectionalAnimations {
forwards: TransitionAnimationPair;
backwards: TransitionAnimationPair;
}

以下示例显示了在根布局文件中的 <style is:global> 标记内定义自定义 bump 动画所需的所有属性:

¥The following example shows all the necessary properties to define a custom bump animation inside a <style is:global> tag in your root layout file:

src/layouts/Layout.astro
---
import { ViewTransitions } from 'astro:transitions';
---
<html lang="en">
<head>
<ViewTransitions />
</head>
<body>
<slot />
</body>
</html>
<style is:global>
@keyframes bump {
0% {
opacity: 0;
transform: scale(1) translateX(200px);
}
50% {
opacity: 0.5;
transform: scale(1.1);
}
100% {
opacity: 1;
transform: scale(1) translateX(0);
}
}
</style>

动画的行为必须在每个使用动画的组件的前置内容中定义:

¥The animation’s behavior must be defined in the frontmatter of every component using the animation:

src/pages/index.astro
---
const anim = {
old: {
name: 'bump',
duration: '0.5s',
easing: 'ease-in',
direction: 'reverse',
},
new: {
name: 'bump',
duration: '0.5s',
easing: 'ease-in-out',
},
};
const customTransition = {
forwards: anim,
backwards: anim,
};
---
<header transition:animate={customTransition}> ... </header>

你在定义自定义动画时具有很大的灵活性。为了实现你想要的结果,你可能希望考虑不寻常的组合,例如使用不同的对象进行前进和后退,或为旧和新提供单独的关键帧动画。

¥You have great flexibility when defining custom animations. To achieve your desired result, you may wish to consider unusual combinations such as using different objects for forward and backward, or providing separate keyframe animations for old and new.

¥Router control

<ViewTransitions /> 路由通过监听以下内容来处理导航:

¥The <ViewTransitions /> router handles navigation by listening to:

  • 单击 <a> 元素。

  • 向后和向前导航事件。

以下选项允许你进一步控制路由内何时进行导航:

¥The following options allow you to further control when navigation occurs within the router:

  • data-astro-reload<a> 标签属性到 强制全页导航

  • data-astro-history="auto | push | replace"<a> 标签属性到 控制浏览器的历史记录

  • navigate(href, options):任何客户端脚本或客户端组件都可以使用的方法

¥Preventing client-side navigation

在某些情况下,你无法通过客户端路由进行导航,因为涉及的两个页面都必须使用 <ViewTransitions /> 路由来防止全页面重新加载。你可能也不希望每次导航更改时都使用客户端路由,而更喜欢在选定的路由上使用传统的页面导航。

¥There are some cases where you cannot navigate via client-side routing since both pages involved must use the <ViewTransitions /> router to prevent a full-page reload. You may also not want client-side routing on every navigation change and would prefer a traditional page navigation on select routes instead.

你可以通过将 data-astro-reload 属性添加到任何 <a><form> 标记来选择退出基于每个链接的客户端路由。此属性将覆盖任何现有的 <ViewTransitions /> 组件,并在导航期间触发浏览器刷新。

¥You can opt out of client-side routing on a per-link basis by adding the data-astro-reload attribute to any <a> or <form> tag. This attribute will override any existing <ViewTransitions /> component and instead trigger a browser refresh during navigation.

以下示例显示仅从主页导航到文章时阻止客户端路由。当从文章列表页面导航到同一页面时,这仍然允许你在共享元素上有动画,例如英雄图片:

¥The following example shows preventing client-side routing when navigating to an article from the home page only. This still allows you to have animation on shared elements, such as a hero image, when navigating to the same page from an article listing page:

src/pages/index.astro
<a href="/articles/emperor-penguins" data-astro-reload>
src/pages/articles.astro
<a href="/articles/emperor-penguins">

具有 data-astro-reload 属性的链接将被路由忽略,并且将发生全页导航。

¥Links with the data-astro-reload attribute will be ignored by the router and a full-page navigation will occur.

¥Trigger navigation

你还可以使用 navigate 通过 <ViewTransitions /> 路由通常不监听的事件来触发客户端导航。astro:transitions/client 模块中的此函数可以在脚本中以及与 客户指令 结合的框架组件中使用。

¥You can also trigger client-side navigation via events not normally listened to by the <ViewTransitions /> router using navigate. This function from the astro:transitions/client module can be used in scripts, and in framework components that are hydrated with a client directive.

以下示例显示了一个 Astro 组件,该组件将访问者导航到他们从菜单中选择的另一个页面:

¥The following example shows an Astro component that navigates a visitor to another page they select from a menu:

src/components/Form.astro
<script>
import { navigate } from 'astro:transitions/client';
// Navigate to the selected option automatically.
document.querySelector('select').onchange = (event) => {
let href = event.target.value;
navigate(href);
};
</script>
<select>
<option value="/play">Play</option>
<option value="/blog">Blog</option>
<option value="/about">About</option>
<option value="/contact">Contact</option>
</select>
src/pages/index.astro
---
import Form from "../components/Form.astro";
import { ViewTransitions } from "astro:transitions";
---
<html>
<head>
<ViewTransitions />
</head>
<body>
<Form />
</body>
</html>

以下示例在 React <Form /> 组件中使用 navigate() 实现了相同的效果:

¥The following example implements the same using navigate() in a React <Form /> component:

src/components/Form.jsx
import { navigate } from "astro:transitions/client";
export default function Form() {
return (
<select onChange={(e) => navigate(e.target.value)}>
<option value="/play">Play</option>
<option value="/blog">Blog</option>
<option value="/about">About</option>
<option value="/contact">Contact</option>
</select>
);
}

然后,<Form /> 组件可以通过客户端指令渲染在使用 <ViewTransitions /> 路由的 Astro 页面上:

¥The <Form /> component can then be rendered on an Astro page that uses the <ViewTransitions /> router, with a client directive:

src/pages/index.astro
---
import Form from "../components/Form.jsx";
import { ViewTransitions } from "astro:transitions";
---
<html>
<head>
<ViewTransitions />
</head>
<body>
<Form client:load />
</body>
</html>

navigate 方法采用以下参数:

¥The navigate method takes these arguments:

  • href(必需) - 要导航到的新页面。

  • options - 具有以下属性的可选对象:

    • history'push' | 'replace' | 'auto'

      • 'push':路由将使用 history.pushState 在浏览器历史记录中创建一个新条目。

      • 'replace':路由将使用 history.replaceState 更新 URL,而不添加新的导航条目。

      • 'auto'(默认):路由将尝试 history.pushState,但如果该 URL 不是可以转换到的 URL,则当前 URL 将保留,浏览器历史记录不会发生任何更改。

    • formData:用于 POST 请求的 FormData 对象。

要在浏览器历史记录中向后和向前导航,你可以将 navigate() 与浏览器的内置 history.back()history.forward()history.go() 功能结合起来。如果在组件的服务器端渲染期间调用 navigate(),则它不会产生任何效果。

¥For backward and forward navigation through the browser history, you can combine navigate() with the built-in history.back(), history.forward() and history.go() functions of the browser. If navigate() is called during the server-side render of your component, it has no effect.

替换浏览器历史记录中的条目

Section titled 替换浏览器历史记录中的条目

¥Replace entries in the browser history

通常,每次导航时,都会将一个新条目写入浏览器的历史记录中。这允许使用浏览器的 backforward 按钮在页面之间导航。

¥Normally, each time you navigate, a new entry is written to the browser’s history. This allows navigation between pages using the browser’s back and forward buttons.

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

¥The <ViewTransitions /> router allows you to overwrite history entries by adding the data-astro-history attribute to any individual <a> tag.

data-astro-history 属性可以设置为与 navigate() 功能的 history 选项 相同的三个值:

¥The data-astro-history attribute can be set to the same three values as the history option of the navigate() function:

data-astro-history'push' | 'replace' | 'auto'

  • 'push':路由将使用 history.pushState 在浏览器历史记录中创建一个新条目。

  • 'replace':路由将使用 history.replaceState 更新 URL,而不添加新的导航条目。

  • 'auto'(默认):路由将尝试 history.pushState,但如果该 URL 不是可以转换到的 URL,则当前 URL 将保留,浏览器历史记录不会发生任何更改。

以下示例导航到 /main 页面,但不向浏览历史记录添加新条目。相反,它会重用历史记录 (/confirmation) 中的当前条目并覆盖它。

¥The following example navigates to the /main page but does not add a new entry to the browsing history. Instead, it reuses the current entry in the history (/confirmation) and overwrites it.

src/pages/confirmation.astro
<a href="/main" data-astro-history="replace">

这样的效果是,如果你从 /main 页面返回,浏览器将不会显示 /confirmation 页面,而是显示其之前的页面。

¥This has the effect that if you go back from the /main page, the browser will not display the /confirmation page, but the page before it.

¥Transitions with forms

Added in: astro@4.0.0

<ViewTransitions /> 路由将触发来自 <form> 元素的页内转换,支持 GETPOST 请求。

¥The <ViewTransitions /> router will trigger in-page transitions from <form> elements, supporting both GET and POST requests.

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

¥By default, Astro submits your form data as multipart/form-data when your method is set to POST. If you want to match the default behavior of web browsers, use the enctype attribute to submit your data encoded as application/x-www-form-urlencoded:

src/components/Form.astro
<form action="/contact" method="POST" enctype="application/x-www-form-urlencoded">
<!-- -->
</form>

你可以使用 data-astro-reload 属性在任何单独的表单上选择退出路由转换:

¥You can opt out of router transitions on any individual form using the data-astro-reload attribute:

src/components/Form.astro
<form action="/contact" data-astro-reload>
<!-- -->
</form>

¥Fallback control

<ViewTransitions /> 路由在支持视图转换的浏览器(即 Chromium 浏览器)中效果最佳,但也包括对其他浏览器的默认后备支持。即使浏览器不支持 View Transitions API,Astro 仍将使用后备选项之一提供浏览器内导航,以获得类似的体验。

¥The <ViewTransitions /> router works best in browsers that support View Transitions (i.e. Chromium browsers), but also includes default fallback support for other browsers. Even if the browser does not support the View Transitions API, Astro will still provide in-browser navigation using one of the fallback options for a comparable experience.

你可以通过在 <ViewTransitions /> 组件上添加 fallback 属性并将其设置为 swapnone 来覆盖 Astro 的默认后备支持:

¥You can override Astro’s default fallback support by adding a fallback property on the <ViewTransitions /> component and setting it to swap or none:

  • animate(默认,推荐) - Astro 会在更新页面内容之前使用自定义属性模拟视图转换。

  • swap - Astro 不会尝试为页面添加动画效果。相反,旧页面将立即被新页面替换。

  • none - Astro 根本不会做任何动画页面转换。相反,你将在不支持的浏览器中获得完整页面导航。

---
import { ViewTransitions } from 'astro:transitions';
---
<title>My site</title>
<ViewTransitions fallback="swap" />

¥Client-side navigation process

使用 <ViewTransitions /> 路由时,会发生以下步骤来生成 Astro 的客户端导航:

¥When using the <ViewTransitions /> router, the following steps occur to produce Astro’s client-side navigation:

  1. A visitor to your site triggers navigation by any of the following actions:

    • Clicking an <a> tag linking internally to another page on your site.
    • Clicking the back button.
    • Clicking the forward button.
  2. The router starts fetching the next page.

  3. The router adds the data-astro-transition attribute to the HTML element with a value of 'forward' or 'back' as appropriate.

  4. The router calls document.startViewTransition. This triggers the browser’s own view transition process. Importantly, the browser screenshots the current state of the page.

  5. Inside the startViewTransition callback, the router performs a swap, which consists of the following sequence of events:

    • The contents of the <head> are swapped out, with some elements kept:

      • Stylesheet DOM nodes are left in if they exist on the new page, to prevent FOUC.
      • Scripts are left in if they exist on the new page.
      • Any other head elements with transition:persist are left in if there is a corresponding element in the new page.
    • The <body> is completely replaced with the new page’s body.

    • Elements marked transition:persist are moved over to the new DOM if they exist on the new page.

    • Scroll position is restored if necessary.

    • The astro:after-swap event is triggered on the document. This is the end of the swap process.

  6. The router waits for any new stylesheets to load before resolving the transition.

  7. The router executes any new scripts added to the page.

  8. The astro:page-load event fires. This is the end of the navigation process.

具有视图转换的脚本行为

Section titled 具有视图转换的脚本行为

¥Script behavior with view transitions

当你将视图转换添加到现有的 Astro 项目时,你的某些脚本可能不再像在全页浏览器刷新后那样在页面导航后重新运行。使用以下信息确保你的脚本按预期执行。

¥When you add view transitions to an existing Astro project, some of your scripts may no longer re-run after page navigation like they did with full-page browser refreshes. Use the following information to ensure that your scripts execute as expected.

¥Script order

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

¥When navigating between pages with the <ViewTransitions /> component, scripts are run in sequential order to match browser behavior.

¥Script re-execution

打包模块脚本 是 Astro 中的默认脚本,只会执行一次。初始执行后,它们将被忽略,即使脚本在转换后存在于新页面上。

¥Bundled module scripts, which are the default scripts in Astro, are only ever executed once. After initial execution they will be ignored, even if the script exists on the new page after a transition.

与打包模块脚本不同,如果 内联脚本 存在于多次访问的页面上,则有可能在用户访问网站期间重新执行。当访问者导航到没有脚本的页面,然后返回到有脚本的页面时,内联脚本也可能会重新执行。

¥Unlike bundled module scripts, inline scripts have the potential to be re-executed during a user’s visit to a site if they exist on a page that is visited multiple times. Inline scripts might also re-execute when a visitor navigates to a page without the script, and then back to one with the script.

Added in: astro@4.5.0

要强制内联脚本在每次转换后重新执行,请添加 data-astro-rerun 属性。向脚本添加任何属性也会隐式添加 is:inline,因此这仅适用于未由 Astro 打包和处理的脚本。

¥To force inline scripts to re-execute after every transition, add the data-astro-rerun property. Adding any attribute to a script also implicitly adds is:inline, so this is only available for scripts that are not bundled and processed by Astro.

<script is:inline data-astro-rerun>...</script>

要确保在客户端导航期间每次加载页面时脚本都会运行,它应该由 生命周期事件 执行。例如,DOMContentLoaded 的事件监听器可以由 astro:page-load 生命周期事件替换。

¥To ensure that a script runs every time a page is loaded during client-side navigation, it should be executed by a lifecycle event. For example, event listeners for DOMContentLoaded can be replaced by the astro:page-load lifecycle event.

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

¥If you have code that sets up a global state in an inline script, this state will need to take into account that the script might execute more than once. Check for the global state in your <script> tag, and conditionally execute your code where possible. This works because window is preserved.

<script is:inline>
if (!window.SomeGlobal) {
window.SomeGlobal = {} // ....
}
</script>

请参阅 添加视图转换教程 以了解更新项目中现有脚本的示例。

¥See the Add View Transitions Tutorial for an example of updating existing scripts in a project.

¥Lifecycle events

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

¥The <ViewTransition /> router fires a number of events on the document during navigation. These events provide hooks into the lifecycle of navigation, allowing you to do things like show indicators that a new page is loading, override default behavior, and restore state as navigation is completing.

导航过程涉及准备阶段,即加载新内容时;DOM 交换阶段,旧页面的内容被新页面的内容替换;完成阶段,执行脚本,报告加载已完成并进行清理工作。

¥The navigation process involves a preparation phase, when new content is loaded; a DOM swap phase, where the old page’s content is replaced by the new page’s content; and a completion phase where scripts are executed, loading is reported as completed and clean-up work is carried out.

Astro 的 View Transition API 生命周期事件按顺序为:

¥Astro’s View Transition API lifecycle events in order are:

虽然某些操作可以在任何事件期间触发,但某些任务只能在特定事件期间执行以获得最佳结果,例如在准备之前显示加载旋转器或在交换内容之前覆盖动画对。

¥While some actions can be triggered during any event, some tasks can only be performed during a specific event for best results, such as displaying a loading spinner before preparation or overriding animation pairs before swapping content.

Added in: astro@3.6.0

在准备阶段开始时、导航开始后(例如,用户单击链接后)、内容加载前触发的事件。

¥An event that fires at the beginning of the preparation phase, after navigation has started (e.g. after the user has clicked a link), but before content is loaded.

该事件用于:

¥This event is used:

  • 在加载开始之前执行某些操作,例如显示加载加载控件。

  • 更改加载,例如加载你在模板中定义的内容,而不是从外部 URL 加载内容。

  • 更改自定义动画的导航的 direction(通常是 forwardbackward)。

下面是使用 astro:before-preparation 事件在内容加载之前加载加载控件并在加载后立即停止它的示例。请注意,以这种方式使用加载器回调允许异步执行代码。

¥Here is an example of using the astro:before-preparation event to load a spinner before the content is loaded and stop it immediately after loading. Note that using the loader callback in this way allows asynchronous execution of code.

<script is:inline>
document.addEventListener('astro:before-preparation', event => {
const originalLoader = event.loader;
event.loader = async function() {
const { startSpinner } = await import('./spinner.js');
const stop = startSpinner();
await originalLoader();
stop();
};
});
</script>

Added in: astro@3.6.0

在新页面的内容已加载并解析到文档中后、准备阶段结束时触发的事件。此事件发生在视图转换阶段之前。

¥An event that fires at the end of the preparation phase, after the new page’s content has been loaded and parsed into a document. This event occurs before the view transitions phase.

此示例使用 astro:before-preparation 事件来启动加载指示器,并使用 astro:after-preparation 事件来停止它:

¥This example uses the astro:before-preparation event to start a loading indicator and the astro:after-preparation event to stop it:

<script is:inline>
document.addEventListener('astro:before-preparation', () => {
document.querySelector('#loading').classList.add('show');
});
document.addEventListener('astro:after-preparation', () => {
document.querySelector('#loading').classList.remove('show');
});
</script>

这是加载加载控件的一个比上面示例更简单的版本:如果监听器的所有代码都可以同步执行,则无需钩子加载器的回调。

¥This is a simpler version of loading a spinner than the example shown above: if all of the listener’s code can be executed synchronously, there is no need to hook into the loader’s callback.

Added in: astro@3.6.0

在新文档(在准备阶段填充)替换当前文档之前触发的事件。此事件发生在视图转换内部,用户仍然看到旧页面的快照。

¥An event that fires before the new document (which is populated during the preparation phase) replaces the current document. This event occurs inside of the view transition, where the user is still seeing a snapshot of the old page.

此事件可用于在交换发生之前进行更改。事件的 newDocument 属性代表传入文档。以下是确保 localStorage 中浏览器的浅色或夜间模式首选项转移到新页面的示例:

¥This event can be used to make changes before the swap occurs. The newDocument property on the event represents the incoming document. Here is an example of ensuring the browser’s light or dark mode preference in localStorage is carried over to the new page:

<script is:inline>
function setDarkMode(document) {
let theme = localStorage.darkMode ? 'dark' : 'light';
document.documentElement.dataset.theme = theme;
}
setDarkMode(document);
document.addEventListener('astro:before-swap', event => {
// Pass the incoming document to set the theme on it
setDarkMode(event.newDocument);
});
</script>

astro:before-swap 事件还可用于更改交换的实现。默认的交换实现会比较头部内容,将持久元素从旧文档移动到 newDocument,然后用新文档的正文替换整个 body

¥The astro:before-swap event can also be used to change the implementation of the swap. The default swap implementation diffs head content, moves persistent elements from the old document to the newDocument, and then replaces the entire body with the body of the new document.

在生命周期的这一点上,你可以选择定义自己的交换实现,例如比较现有文档的全部内容(其他一些路由会这样做):

¥At this point of the lifecycle, you could choose to define your own swap implementation, for example to diff the entire contents of the existing document (which some other routers do):

<script is:inline>
document.addEventListener('astro:before-swap', event => {
event.swap = () => {
diff(document, event.newDocument);
};
});
</script>

¥Building a custom swap function

Added in: astro@4.15.0

astro:transitions/client 模块的 swapFunctions 对象提供了五个实用函数来处理特定的交换相关任务,包括处理文档属性、页面元素和脚本执行。这些函数可直接用于定义自定义交换实现。

¥The swapFunctions object of the astro:transitions/client module provides five utility functions that handle specific swap-related tasks, including handling document attributes, page elements, and script execution. These functions can be used directly to define a custom swap implementation.

以下示例演示如何使用这些函数重新创建 Astro 的内置交换实现:

¥The following example demonstrates how to use these functions to recreate Astro’s built-in swap implementation:

<script>
import { swapFunctions } from 'astro:transitions/client';
// substitutes window.document with doc
function mySwap(doc: Document) {
swapFunctions.deselectScripts(doc);
swapFunctions.swapRootAttributes(doc);
swapFunctions.swapHeadElements(doc);
const restoreFocusFunction = swapFunctions.saveFocus();
swapFunctions.swapBodyElement(doc.body, document.body);
restoreFocusFunction();
};
...
event.swap = () => mySwap(event.newDocument);
...
<script>

自定义交换实现可以从此模板开始,并根据需要使用自定义逻辑添加或替换各个步骤。

¥Custom swap implementations can start with this template and add or replace individual steps with custom logic as needed.

新页面替换旧页面后立即触发的事件。你可以在 document 上监听此事件,并触发在新页面的 DOM 元素渲染和脚本运行之前发生的操作。

¥An event that fires immediately after the new page replaces the old page. You can listen to this event on the document and trigger actions that will occur before the new page’s DOM elements render and scripts run.

当在传出页面上监听此事件时,它有助于传递和恢复需要转移到新页面的 DOM 上的任何状态。

¥This event, when listened to on the outgoing page, is useful to pass along and restore any state on the DOM that needs to transfer over to the new page.

这是生命周期中的最新点,例如,添加夜间模式类名称 (<html class="dark-mode">) 仍然是安全的,尽管你可能希望在较早的事件中这样做。

¥This is the latest point in the lifecycle where it is still safe to, for example, add a dark mode class name (<html class="dark-mode">), though you may wish to do so in an earlier event.

astro:after-swap 事件在浏览器历史记录更新并设置滚动位置后立即发生。因此,针对此事件的一种用途是覆盖历史导航的默认滚动恢复。以下示例将每个导航的水平和垂直滚动位置重置为页面的左上角。

¥The astro:after-swap event occurs immediately after the browser history has been updated and the scroll position has been set. Therefore, one use of targeting this event is to override the default scroll restore for history navigation. The following example resets the horizontal and vertical scroll position to the top left corner of the page for each navigation.

document.addEventListener('astro:after-swap',
() => window.scrollTo({ left: 0, top: 0, behavior: 'instant' }))

在页面导航结束时、用户可见新页面并加载阻止样式和脚本后触发的事件。你可以在 document 上收听此事件。

¥An event that fires at the end of page navigation, after the new page is visible to the user and blocking styles and scripts are loaded. You can listen to this event on the document.

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

¥The <ViewTransitions /> component fires this event both on initial page navigation for a pre-rendered page and on any subsequent navigation, either forwards or backwards.

你可以使用此事件在每个页面导航上运行代码,例如设置在导航过程中可能丢失的事件监听器。

¥You can use this event to run code on every page navigation, for example to set up event listeners that would otherwise be lost during navigation.

<script>
document.addEventListener('astro:page-load', () => {
// This runs on first page load and after every navigation.
setupStuff(); // e.g. add event listeners
});
</script>

¥Accessibility

启用客户端路由和动画页面转换都会带来可访问性挑战,Astro 的目标是让选择视图转换的网站尽可能默认为可访问。

¥Enabling client-side routing and animating page transitions both come with accessibility challenges, and Astro aims to make sites opting in to View Transitions as accessible-by-default as possible.

¥Route announcement

Added in: astro@3.2.0

<ViewTransitions /> 组件包括一个路由播音器,用于在客户端路由期间进行页面导航。无需配置或操作即可启用此功能。

¥The <ViewTransitions /> component includes a route announcer for page navigation during client-side routing. No configuration or action is needed to enable this.

辅助技术通过在导航后宣布新的页面标题,让访问者知道页面已更改。当使用服务器端路由与传统的全页浏览器刷新时,默认情况下会在新页面加载后发生这种情况。在客户端路由中,<ViewTransitions /> 组件执行此操作。

¥Assistive technologies let visitors know that the page has changed by announcing the new page title after navigation. When using server-side routing with traditional full-page browser refreshes, this happens by default after the new page loads. In client-side routing, the <ViewTransitions /> component performs this action.

为了将路由公告添加到客户端路由,该组件将一个元素添加到新页面,并将 aria-live 属性设置为 assertive。这告诉 AT(辅助技术)立即宣布。该组件还按优先级顺序检查以下内容,以确定公告文本:

¥To add route announcement to client-side routing, the component adds an element to the new page with the aria-live attribute set to assertive. This tells AT (assistive technology) to announce immediately. The component also checks for the following, in priority order, to determine the announcement text:

  • <title>(如果存在)。

  • 它找到的第一个 <h1>

  • 页面的 pathname

我们强烈建议你始终在每个页面中包含 <title> 以方便访问。

¥We strongly recommend you always include a <title> in each page for accessibility.

Astro 的 <ViewTransitions /> 组件包含一个 CSS 媒体查询,每当检测到 prefer-reduced-motion 设置时,该查询就会禁用所有视图转换动画,包括回退动画。相反,浏览器将简单地交换 DOM 元素,而无需动画。

¥Astro’s <ViewTransitions /> component includes a CSS media query that disables all view transition animations, including fallback animation, whenever the prefer-reduced-motion setting is detected. Instead, the browser will simply swap the DOM elements without an animation.

Astro 中文网 - 粤ICP备13048890号