跳转到内容

前端框架

在不牺牲你喜爱的组件框架的前提下,构建你的 Astro 网站。使用你选择的 UI 框架创建 Astro 岛屿

Astro 通过官方集成支持多种流行框架,包括 ReactPreactSvelteVueSolidJSAlpineJS

在我们的集成目录中,你可以找到更多由社区维护的框架集成(例如 Angular、Qwik、Elm)。

前端框架

你可以在你的项目中安装和配置一个或多个这样的 Astro 集成。

有关安装和配置 Astro 集成的更多详细信息,请参阅集成指南

像使用 Astro 组件一样,在你的 Astro 页面、布局和组件中使用你的 JavaScript 框架组件!你所有的组件都可以放在 /src/components 目录下,或者以任何你喜欢的方式组织。

要使用框架组件,请在你的 Astro 组件脚本中从其相对路径导入。然后,在组件模板中,将该组件与其他组件、HTML 元素和类 JSX 表达式一起使用。

src/pages/static-components.astro
---
import MyReactComponent from '../components/MyReactComponent.jsx';
---
<html>
<body>
<h1>Use React components directly in Astro!</h1>
<MyReactComponent />
</body>
</html>

默认情况下,你的框架组件只会在服务器上渲染成静态 HTML。这对于那些非交互式的模板组件很有用,可以避免向客户端发送不必要的 JavaScript。

框架组件可以通过使用 client:* 指令来使之可交互(注水)。这些是组件属性,用于确定何时将组件的 JavaScript 发送到浏览器。

除了 client:only,对于所有其他的客户端指令,你的组件将首先在服务器上渲染以生成静态 HTML。组件的 JavaScript 将根据你选择的指令发送到浏览器。然后,组件将进行注水并变得可交互。

src/pages/interactive-components.astro
---
// Example: hydrating framework components in the browser.
import InteractiveButton from '../components/InteractiveButton.jsx';
import InteractiveCounter from '../components/InteractiveCounter.jsx';
import InteractiveModal from '../components/InteractiveModal.svelte';
---
<!-- This component's JS will begin importing when the page loads -->
<InteractiveButton client:load />
<!-- This component's JS will not be sent to the client until
the user scrolls down and the component is visible on the page -->
<InteractiveCounter client:visible />
<!-- This component won't render on the server, but will render on the client when the page loads -->
<InteractiveModal client:only="svelte" />

渲染组件所需的 JavaScript 框架(React、Svelte 等)将与组件自身的 JavaScript 一起发送到浏览器。如果页面上有两个或多个组件使用相同的框架,则该框架只会发送一次。

对于 UI 框架组件,有几个可用的注水指令:client:loadclient:idleclient:visibleclient:media={QUERY}client:only={FRAMEWORK}

有关这些注水指令的完整描述及其用法,请参阅我们的指令参考页面。

你可以在同一个 Astro 组件中导入并渲染来自多个框架的组件。

src/pages/mixing-frameworks.astro
---
// Example: Mixing multiple framework components on the same page.
import MyReactComponent from '../components/MyReactComponent.jsx';
import MySvelteComponent from '../components/MySvelteComponent.svelte';
import MyVueComponent from '../components/MyVueComponent.vue';
---
<div>
<MySvelteComponent />
<MyReactComponent />
<MyVueComponent />
</div>

Astro 会根据文件扩展名识别并渲染你的组件。为了区分使用相同文件扩展名的框架(例如 React 和 Preact),需要在渲染多个 JSX 框架时进行额外配置

你可以从 Astro 组件向框架组件传递 props

src/pages/frameworks-props.astro
---
import TodoList from '../components/TodoList.jsx';
import Counter from '../components/Counter.svelte';
---
<div>
<TodoList initialTodos={["learn Astro", "review PRs"]} />
<Counter startingCount={1} />
</div>

传递给使用 client:* 指令的交互式框架组件的 Props 必须是可序列化的:即转换为适合通过网络传输或存储的格式。然而,Astro 并不序列化所有类型的数据结构。因此,可以作为 props 传递给已注水组件的内容有一些限制。

支持以下 prop 类型:普通对象、numberstringArrayMapSetRegExpDateBigIntURLUint8ArrayUint16ArrayUint32ArrayInfinity

传递给组件的不支持的数据结构,例如函数,只能在组件的服务端渲染期间使用,不能用于提供交互性。例如,不支持将函数传递给已注水的组件,因为 Astro 无法以一种使函数在客户端可执行的方式从服务器传递它们。

在 Astro 组件内部,你可以将子组件传递给框架组件。每个框架都有自己的模式来引用这些子组件:React、Preact 和 Solid 都使用一个名为 children 的特殊 prop,而 Svelte 和 Vue 则使用 <slot /> 元素。

src/pages/component-children.astro
---
import MyReactSidebar from '../components/MyReactSidebar.jsx';
---
<MyReactSidebar>
<p>Here is a sidebar with some text and a button.</p>
</MyReactSidebar>

此外,你可以使用具名插槽将特定的子组件分组。

对于 React、Preact 和 Solid,这些插槽将被转换为一个顶层 prop。使用 kebab-case 的插槽名将被转换为 camelCase

src/pages/named-slots.astro
---
import MySidebar from '../components/MySidebar.jsx';
---
<MySidebar>
<h2 slot="title">Menu</h2>
<p>Here is a sidebar with some text and a button.</p>
<ul slot="social-links">
<li><a href="https://twitter.com/astrodotbuild">Twitter</a></li>
<li><a href="https://github.com/withastro">GitHub</a></li>
</ul>
</MySidebar>
src/components/MySidebar.jsx
export default function MySidebar(props) {
return (
<aside>
<header>{props.title}</header>
<main>{props.children}</main>
<footer>{props.socialLinks}</footer>
</aside>
)
}

对于 Svelte 和 Vue,这些插槽可以使用带有 name 属性的 <slot> 元素来引用。使用 kebab-case 的插槽名将被保留。

src/components/MySidebar.svelte
<aside>
<header><slot name="title" /></header>
<main><slot /></main>
<footer><slot name="social-links" /></footer>
</aside>

在 Astro 文件中,框架组件的子组件也可以是已注水的组件。这意味着你可以递归地嵌套来自任何这些框架的组件。

src/pages/nested-components.astro
---
import MyReactSidebar from '../components/MyReactSidebar.jsx';
import MyReactButton from '../components/MyReactButton.jsx';
import MySvelteButton from '../components/MySvelteButton.svelte';
---
<MyReactSidebar>
<p>Here is a sidebar with some text and a button.</p>
<div slot="actions">
<MyReactButton client:idle />
<MySvelteButton client:idle />
</div>
</MyReactSidebar>

这允许你用你喜欢的 JavaScript 框架构建整个“应用”,并通过一个父组件将它们渲染到 Astro 页面。

我可以在我的框架组件中使用 Astro 组件吗?

标题为“我可以在我的框架组件中使用 Astro 组件吗?”的部分

任何 UI 框架组件都会成为该框架的一个“岛屿”。这些组件必须完全按照该框架的有效代码编写,只使用其自身的导入和包。你不能在 UI 框架组件(例如 .jsx.svelte)中导入 .astro 组件。

然而,你可以使用 Astro 的 <slot /> 模式,将由 Astro 组件生成的静态内容作为子组件传递给.astro 组件内部的框架组件。

src/pages/astro-children.astro
---
import MyReactComponent from '../components/MyReactComponent.jsx';
import MyAstroComponent from '../components/MyAstroComponent.astro';
---
<MyReactComponent>
<MyAstroComponent slot="name" />
</MyReactComponent>

如果你尝试用 client: 修饰符为一个 Astro 组件注水,你会得到一个错误。

Astro 组件是纯 HTML 模板组件,没有客户端运行时。但是,你可以在你的 Astro 组件模板中使用 <script> 标签向浏览器发送在全局作用域中执行的 JavaScript。

贡献 社区 赞助