Skip to content

模板指令参考

模板指令 是一种特殊的 HTML 属性,可在任何 Astro 组件模板(.astro 文件)内使用,有些也可以在 .mdx 文件中使用。

Template directives are a special kind of HTML attribute available inside of any Astro component template (.astro files), and some can also be used in .mdx files.

模板指令用于以某种方式控制元素或组件的行为。 模板指令可以启用一些编译器功能,使你的生活更轻松(例如使用 class:list 而不是 class)。 或者,指令可以告诉 Astro 编译器对该组件执行一些特殊操作(例如使用 client:load 进行水合)。

Template directives are used to control an element or component’s behavior in some way. A template directive could enable some compiler feature that makes your life easier (like using class:list instead of class). Or, a directive could tell the Astro compiler to do something special with that component (like hydrating with client:load).

本页描述了 Astro 中可用的所有模板指令以及它们的工作原理。

This page describes all of the template directives available to you in Astro, and how they work.

为了使模板指令有效,它必须:

For a template directive to be valid, it must:

  • 使用 X:Y 形式(例如:client:load)在其名称中包含冒号 :
  • 对编译器可见(例如:如果 attr 包含指令,<X {...attr}> 将不起作用)。

一些模板指令(但不是全部)可以采用自定义值:

  • <X client:load /> (没有任何值)
  • <X class:list={['some-css-class']} /> (采用一个数组)

模板指令永远不会直接包含在组件的最终 HTML 输出中。

A template directive is never included directly in the final HTML output of a component.

class:list={...} 获取类值数组并将它们转换为类字符串。 这是由 @lukeed 流行的 clsx 辅助程序库提供支持的。

class:list={...} takes an array of class values and converts them into a class string. This is powered by @lukeed’s popular clsx helper library.

class:list 采用几个不同的可能值类型的数组:

  • string: 添加到元素 class
  • Object: 所有真实密钥都添加到元素 class
  • Array: flattened
  • falsenullundefined: skipped
<!-- This -->
<span class:list={[ 'hello goodbye', { world: true }, [ 'friend' ] ]} />
<!-- Becomes -->
<span class="hello goodbye world friend"></span>

set:html={string} 将 HTML 字符串注入到元素中,类似于设置 el.innerHTML

set:html={string} injects an HTML string into an element, similar to setting el.innerHTML.

Astro 不会自动转义该值! 确保你信任该值,或者在将其传递给模板之前已手动对其进行转义。 忘记这样做会让你面临 跨站脚本 (XSS) 攻击。

The value is not automatically escaped by Astro! Be sure that you trust the value, or that you have escaped it manually before passing it to the template. Forgetting to do this will open you up to Cross Site Scripting (XSS) attacks.

---
const rawHTMLString = "Hello <strong>World</strong>"
---
<h1>{rawHTMLString}</h1>
<!-- Output: <h1>Hello &lt;strong&gt;World&lt;/strong&gt;</h1> -->
<h1 set:html={rawHTMLString} />
<!-- Output: <h1>Hello <strong>World</strong></h1> -->

你还可以在 <Fragment> 上使用 set:html 以避免添加不必要的封装元素。 从 CMS 获取 HTML 时,这尤其有用。

You can also use set:html on a <Fragment> to avoid adding an unnecessary wrapper element. This can be especially useful when fetching HTML from a CMS.

---
const cmsContent = await fetchHTMLFromMyCMS();
---
<Fragment set:html={cmsContent}>

set:html={Promise<string>} 将 HTML 字符串注入到封装在 Promise 中的元素中。

set:html={Promise<string>} injects an HTML string into an element that is wrapped in a Promise.

这可用于注入外部存储的 HTML,例如数据库中的 HTML。

This can be used to inject HTML stored externally, such as in a database.

---
import api from '../db/api.js';
---
<article set:html={api.getArticle(Astro.props.id)}></article>

set:html={Promise<Response>}响应 注入到元素中。

set:html={Promise<Response>} injects a Response into an element.

这在使用 fetch() 时最有帮助。 例如,从以前的静态站点生成器中获取旧帖子。

This is most helpful when using fetch(). For example, fetching old posts from a previous static-site generator.

<article set:html={fetch('http://example/old-posts/making-soup.html')}></article>

set:html 可用于任何标记,并且不必包含 HTML。 例如,在 <script> 标记上使用 JSON.stringify() 可将 JSON-LD 架构添加到页面。

set:html can be used on any tag and does not have to include HTML. For example, use with JSON.stringify() on a <script> tag to add a JSON-LD schema to your page.

<script type="application/ld+json" set:html={JSON.stringify({
"@context": "https://schema.org/",
"@type": "Person",
name: "Houston",
hasOccupation: {
"@type": "Occupation",
name: "Astronaut"
}
})}/>

set:text={string} 将文本字符串注入到元素中,类似于设置 el.innerText。 与 set:html 不同,传递的 string 值会被 Astro 自动转义。

set:text={string} injects a text string into an element, similar to setting el.innerText. Unlike set:html, the string value that is passed is automatically escaped by Astro.

这相当于直接将变量传递到模板表达式中(例如:<div>{someText}</div>),因此该指令不常用。

This is equivalent to just passing a variable into a template expression directly (ex: <div>{someText}</div>) and therefore this directive is not commonly used.

这些指令控制 UI 框架组件 在页面上的水合方式。

These directives control how UI Framework components are hydrated on the page.

默认情况下,UI 框架组件不会在客户端中进行水合。 如果未提供 client:* 指令,则其 HTML 将在没有 JavaScript 的情况下渲染到页面上。

By default, a UI Framework component is not hydrated in the client. If no client:* directive is provided, its HTML is rendered onto the page without JavaScript.

客户端指令只能用在直接导入到 .astro 组件中的 UI 框架组件上。 使用 动态标签通过 components 属性传递的自定义组件 时不支持水合指令。

A client directive can only be used on a UI framework component that is directly imported into a .astro component. Hydration directives are not supported when using dynamic tags and custom components passed via the components prop.

  • 优先事项: 高的
  • 对…有用: 需要尽快进行交互的立即可见的 UI 元素。

在页面加载时立即加载并水合组件 JavaScript。

Load and hydrate the component JavaScript immediately on page load.

<BuyButton client:load />
  • 优先事项: 中等的
  • 对…有用: 不需要立即交互的优先级较低的 UI 元素。

页面完成初始加载并且 requestIdleCallback 事件触发后,加载并水合组件 JavaScript。 如果你使用的浏览器不支持 requestIdleCallback,则使用文档 load 事件。

Load and hydrate the component JavaScript once the page is done with its initial load and the requestIdleCallback event has fired. If you are in a browser that doesn’t support requestIdleCallback, then the document load event is used.

<ShowHideButton client:idle />
  • 优先事项: 低的
  • 对…有用: 低优先级 UI 元素要么位于页面下方 (“首屏以下”),要么加载时需要占用大量资源,如果用户从未见过该元素,你根本不希望加载它们。

一旦组件进入用户的视口,就加载并混合组件 JavaScript。 这在内部使用 IntersectionObserver 来跟踪可见性。

Load and hydrate the component JavaScript once the component has entered the user’s viewport. This uses an IntersectionObserver internally to keep track of visibility.

<HeavyImageCarousel client:visible />
  • 优先事项: 低的
  • 对…有用: 侧边栏切换或其他可能仅在某些屏幕尺寸上可见的元素。

一旦满足特定的 CSS 媒体查询,client:media={string} 就会加载并水合组件 JavaScript。

client:media={string} loads and hydrates the component JavaScript once a certain CSS media query is met.

:::note 注意 如果组件已经通过 CSS 中的媒体查询隐藏和显示,那么仅使用 client:visible 而不将相同的媒体查询传递到指令中会更容易。 :::

<SidebarToggle client:media="(max-width: 50em)" />

client:only={string} skips HTML 服务器渲染,并且仅在客户端上渲染。 它的行为与 client:load 类似,它在页面加载时立即加载、渲染和水合组件。

client:only={string} skips HTML server-rendering, and renders only on the client. It acts similar to client:load in that it loads, renders and hydrates the component immediately on page load.

你必须将组件的正确框架作为值传递! 因为 Astro 不会在你构建期间/在服务器上运行该组件,所以 Astro 不知道你的组件使用什么框架,除非你明确告诉它。

You must pass the component’s correct framework as a value! Because Astro doesn’t run the component during your build / on the server, Astro doesn’t know what framework your component uses unless you tell it explicitly.

<SomeReactComponent client:only="react" />
<SomePreactComponent client:only="preact" />
<SomeSvelteComponent client:only="svelte" />
<SomeVueComponent client:only="vue" />
<SomeSolidComponent client:only="solid-js" />

从 Astro 2.6.0 开始,集成还可以添加自定义 client:* 指令来更改组件水合的方式和时间。

Since Astro 2.6.0, integrations can also add custom client:* directives to change how and when components should be hydrated.

访问 addClientDirective API 页面以了解有关创建自定义客户端指令的更多信息。

Visit the addClientDirective API page to learn more about creating a custom client directive.

这些指令只能用在 HTML <script><style> 标记上,以控制客户端 JavaScript 和 CSS 在页面上的处理方式。

These directives can only be used on HTML <script> and <style> tags, to control how your client-side JavaScript and CSS are handled on the page.

默认情况下,Astro 自动将 <style> CSS 规则的范围限定到组件。 你可以使用 is:global 指令选择退出此行为。

By default, Astro automatically scopes <style> CSS rules to the component. You can opt-out of this behavior with the is:global directive.

当包含该组件时,is:global 使 <style> 标记的内容在页面上全局应用。 这会禁用 Astro 的 CSS 作用域系统。 这相当于用 :global() 将所有选择器封装在 <style> 标记内。

is:global makes the contents of a <style> tag apply globally on the page when the component is included. This disables Astro’s CSS scoping system. This is equivalent to wrapping all of the selectors within a <style> tag with :global().

你可以将 <style><style is:global> 组合在同一个组件中,以创建一些全局样式规则,同时仍然限定大部分组件 CSS 的范围。

You can combine <style> and <style is:global> together in the same component, to create some global style rules while still scoping most of your component CSS.

📚 有关全局样式如何工作的更多详细信息,请参阅 样式和 CSS 页面。

📚 See the Styling & CSS page for more details about how global styles work.

<style is:global>
body a { color: red; }
</style>

默认情况下,Astro 将处理、优化和打包在页面上看到的任何 <script><style> 标签。 你可以使用 is:inline 指令选择退出此行为。

By default, Astro will process, optimize, and bundle any <script> and <style> tags that it sees on the page. You can opt-out of this behavior with the is:inline directive.

is:inline 告诉 Astro 在最终输出 HTML 中按原样保留 <script><style> 标记。 内容不会被处理、优化或打包。 这限制了一些 Astro 功能,例如导入 npm 包或使用 Sass 等编译为 CSS 的语言。

is:inline tells Astro to leave the <script> or <style> tag as-is in the final output HTML. The contents will not be processed, optimized, or bundled. This limits some Astro features, like importing an npm package or using a compile-to-CSS language like Sass.

is:inline 指令意味着 <style><script> 标签:

The is:inline directive means that <style> and <script> tags:

  • 不会被打包到外部文件中。 这意味着控制外部文件加载的 诸如 defer 之类的属性 将不起作用。
  • 不会进行数据去重—该元素将出现与渲染一样多的次数。
  • 不会相对于 .astro 文件解析其 import/@import/url() 引用。
  • 将在最终输出 HTML 中准确地渲染在其创作位置。
  • 样式将是全局的,并且不限于组件。

:::caution 提醒 只要在 <script><style> 标记上使用除 src 之外的任何属性,就隐含 is:inline 指令。 :::

<style is:inline>
/* inline: relative & npm package imports are not supported. */
@import '/assets/some-public-styles.css';
span { color: green; }
</style>
<script is:inline>
/* inline: relative & npm package imports are not supported. */
console.log('I am inlined right here in the final output HTML.');
</script>

📚 了解 客户端脚本 如何在 Astro 组件中工作。

📚 See how client-side scripts work in Astro components.

define:vars={...} 可以将服务器端变量从组件 frontmatter 传递到客户端 <script><style> 标记。 支持任何 JSON 可序列化的 frontmatter 变量,包括通过 Astro.props 传递到组件的 props。 值用 JSON.stringify() 序列化。

define:vars={...} can pass server-side variables from your component frontmatter into the client <script> or <style> tags. Any JSON-serializable frontmatter variable is supported, including props passed to your component through Astro.props. Values are serialized with JSON.stringify().

---
const foregroundColor = "rgb(221 243 228)";
const backgroundColor = "rgb(24 121 78)";
const message = "Astro is awesome!";
---
<style define:vars={{ textColor: foregroundColor, backgroundColor }}>
h1 {
background-color: var(--backgroundColor);
color: var(--textColor);
}
</style>
<script define:vars={{ message }}>
alert(message);
</script>

:::caution 提醒 在 <script> 标记上使用 define:vars 意味着 is:inline 指令,这意味着你的脚本不会被打包,而是会直接内联到 HTML 中。

Using define:vars on a <script> tag implies the is:inline directive, which means your scripts won’t be bundled and will be inlined directly into the HTML.

这是因为当 Astro 打包脚本时,即使你在一页上多次包含包含该脚本的组件,它也会包含并运行该脚本一次。 define:vars 需要一个脚本来使用每组值重新运行,因此 Astro 创建一个内联脚本。

This is because when Astro bundles a script, it includes and runs the script once even if you include the component containing the script multiple times on one page. define:vars requires a script to rerun with each set of values, so Astro creates an inline script instead.

对于脚本,请尝试使用 手动将变量传递给脚本。 :::

is:raw 指示 Astro 编译器将该元素的任何子元素视为文本。 这意味着该组件内部所有特殊的 Astro 模板语法都将被忽略。

is:raw instructs the Astro compiler to treat any children of that element as text. This means that all special Astro templating syntax will be ignored inside of this component.

例如,如果你有一个将某些文本转换为 HTML 的自定义 Katex 组件,你可以让用户执行以下操作:

For example, if you had a custom Katex component that converted some text to HTML, you could have users do this:

---
import Katex from '../components/Katex.astro';
---
<Katex is:raw>Some conflicting {syntax} here</Katex>