从零开始使用 Astro 的实用指南

从零开始,使用,astro,实用,指南 · 浏览次数 : 593

小编点评

**文章概述** 文章介绍了Astro框架,以及如何使用Astro框架创建动态页面。 **主要内容** * Astro框架是一个 Island Architecture 的静态网站构建工具。 * Astro框架使用静态 HTML 文件和 JavaScript来构建页面。 * Astro框架提供一些指令,可以控制页面如何被渲染。 * 使用Astro框架创建动态页面需要手动构建 HTML 文件和 JavaScript。 * Astro框架允许用户快速构建和部署静态网站。 **结论** 文章介绍了Astro框架,以及如何使用Astro框架创建动态页面。

正文

在这个实用的Astro指南中,我将指导你完成设置过程,并告诉你如何构造你的文件。你将学习如何添加页面、交互式组件,甚至是markdown文章。我还会告诉你如何从服务器上获取数据,创建布局,并使用vanilla JavaScript和其他框架添加互动性。准备好享受一些动手的乐趣,因为我们将一起创建一个小型的网站实例。我们将构建一个多页面的网站,包括一个博客。

在这篇文章末尾,你会很好地理解Astro是如何工作的,以及你如何使用它来更快地创建高效的网站。开始吧!

  • 什么是Astro框架?
  • Astro入门
  • Astro项目结构
  • Astro页面
  • Astro组件
  • 添加脚本
  • Astro布局
  • 元素
  • Astro组件props
  • Astro中的样式
  • 获取数据
  • 管理内容
  • 嵌套布局
  • 加载本地文件
  • 添加脚本
  • 使用UI框架
  • 指令
  • 构建和发布
  • 总结

什么是Astro框架?

作为开发人员,我们知道,在建设网站时,创造一个良好的用户体验是关键。而用户最喜欢的是什么?快速的网站,不浪费他们的时间。有了Astro,我们可以通过向浏览器发送更少的代码来实现这一目标。

我们都有自己喜欢的UI框架,使我们的生活更轻松,但它们可能会以沉重的网站为代价。但是有了Astro,我们就可以拥有两个世界中最好的东西。它允许我们用我们最喜欢的框架甚至多个框架同时构建我们的网站,但它在构建时将它们渲染成静态HTML。因此,我们可以为我们的用户创建一个快速的网站,而不牺牲现代开发者的体验。

但Astro并没有止步不前。它还允许我们在需要时加入动态的客户端JavaScript,这意味着我们可以在网站上拥有可交互的组件,但只在必要时进行。换句话说,Astro允许你从简单的开始,在需要时增加复杂性。

简而言之,Astro是一个强大的框架,它同时支持静态网站生成(SSG)和服务端渲染(SSR),帮助我们建立快速的、基于内容的网站,同时考虑到开发人员的体验。它轻量、高效、灵活,使它成为创建内容丰富的网站的合适选择,如博客、投资组合、文档和一些电子商务网站。如果你想创建一个具有大量交互的复杂应用程序,Astro可能不是你的正确选择。相反,你可以考虑其他工具比如Next.js。

很好,现在我们对Astro是什么以及它能做什么有了很好的了解。接下来,让我们继续研究,看看我们能一起构造些什么。

Astro入门

首先,让我们安装Astro并创建项目的模板。确保你的电脑上安装了Node.js v16.12.0或者更高版本。

npm create astro@latest

或者:

yarn create astro@latest

CLI会询问你的项目名称和你是否要使用Typescript。此外,它还会给你几个选项,告诉你如何设置你的项目。在本教程中,我选择了"一个空项目 "选项。

以下是我与Astro CLI的小型对话:

image.png

一旦你在编辑器中打开你的项目,你可以安装Astro的扩展。由于Astro有自己的文件扩展和语法,你可能想为你的编辑器安装其扩展。这里是VSCode的Astro扩展的链接,它不仅仅为你高亮语法,还能做得更多。

现在你可以用以下命令来运行你的项目。不需要安装任何依赖。

npm run dev

打开浏览器,访问http://localhost:3000/ ,一切就绪。

Astro项目结构

Astro的文件结构相当直截了当。

  • src:你的源码(组件、页面、样式等等)
  • public:你的静态资源(字体、图标等等)

src/pages目录下,Astro创建了一个index.astro,你可以认为这是index.html

image.png

值得注意的是,src/content/是Astro的一个保留目录。Astro v2.0引入了Collections API,用于将你的Markdown和MDX文件组织成内容集合。这个API保留了src/content/作为一个特殊的文件夹。

Astro页面

好了,让我们来谈谈Astro的页面。Astro页面处理路由、数据加载以及网站上每个页面的整体布局。它们是具有不同扩展名的文件,存在于src/pages/子目录中。

在Astro中,我们有不同类型的页面,包括.astro.md.mdx.html甚至是.js/.ts。每种文件类型都有不同的用途,可以用不同的方式来创建你的页面。

Astro使用一种称为基于文件路由的路由策略,这意味着你的src/pages/目录中的每个文件都会根据其文件路径成为你网站上的一个端点。这使得你的页面具有灵活性,并易于组织。

在本教程中,我们主要使用.astro.md文件来创建页面。注意,如果你使用.html页面,一些关键的Astro特性在HTML组件中不被支持。

现在让我们来创建第二个页面,看看它是如何工作的。你所需要做的就是在src/pages目录下创建一个紧挨着index.astro的文件。

我打算把它命名为about.astro,并在里面写上非常简单的标记语言:

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <title>About</title>
  </head>
  <body>
    <h1>About</h1>
    <p>Jamstack development agency.</p>
  </body>
</html>

现在你可以访问localhost:3000/about,在你的浏览器中看到这个页面。正如你所看到的,只要你把文件添加到pages文件夹中,/about路由就能立即发挥作用。

你可以更新内容,甚至添加你自己的内部样式,Astro将为你实时预览。所以不需要安装任何实时重载的NPM包或此类东西。

为了能够在页面之间轻松导航,我打算在我的index.astroabout.astro文件中添加导航:

<body>
  <nav>
    <a href="/">Home</a>
    <a href="/about">About</a>
  </nav>    
  <h1>About</h1>
  <p>Jamstack development agency.</p>
</body>

但你不希望每次在导航中增加一个链接时都要更新所有的页面,对吗?

这就是组件发挥作用的地方,让你不要重复你自己(DRY)。

Astro组件

Astro组件是任何Astro项目的基本构成模块。它们有两个主要部分:

  • 组件脚本
  • 组件模板

Astro组件长这样:

---
// Component Script (JavaScript)
---
<!-- Component Template (HTML + JS Expressions) -->

让我们为项目添加第一个组件。

我打算创建一个src/components目录,并在里面添加一个header.astro文件。接着,我会移动导航标记到Header组件中。目前为止,我们的组件的脚本部分是空白的。

---

---
<nav>
  <a href="/">Home</a>
  <a href="/about">About</a>
</nav>

下一步是将该组件添加到我们的页面中。为了做到这一点,我们需要导入该组件。因此,打开你的about.astro文件,在文件的顶部添加以下导入内容:

---
import Header from '../components/Header.astro';
---
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <title>About</title>
  </head>
  <body>
    <h1>About</h1>
    <p>Jamstack development agency.</p>
  </body>
</html>

现在,header组件已经导入了,可以这么使用:

<body>
  <Header />
  <h1>About</h1>
</body>

对主页做同样的事情,也就是pages目录中的index.astro文件。

现在,如果你在浏览器中查看这些页面,你应该看到header展现良好。

最后,我将把我们的logo和一些语义标记,与一个容器一起添加到我们的header中,这样我稍后可以添加一些样式:

<header>
  <div class="container">
    <a class="logo" href="/">
      <svg><!-- SVG Logo goes here --></svg>
    </a>
    <nav>
      <a href="/">Home</a>
      <a href="/about">About</a>
    </nav>
  </div>
</header>

这就是Astro的厉害之处。到目前为止,我们已经制作了页面,并向其添加了组件,而几乎不需要写任何HTML以外的东西。

添加脚本

代码栅栏是你的Astro组件的脚本部分。你可以用栅栏来写任何你需要的JavaScript来渲染你的模板。你甚至可以写TypeScript!

---
// The code fence area
---

例如,在上一节中,我在我的代码栅栏中添加了一个导入行,将Header组件添加到我的页面。我们将继续讨论我们在代码栅栏中还能做什么。

它被称为代码栅栏的原因是,无论你在其中写了什么JavaScript代码,都会被"围起来",不能逃到浏览器中去,也不能到你的用户手中。你在这里写的一切只是为了帮助你的组件模板。

让我们回到我们的页面,在页面的代码栅栏中添加一个变量,用于存储页面标题:

---
import Header from '../components/Header.astro';
const pageTitle = 'Bejamas';
---
<html lang="en">
  <head>
    <title>{pageTitle}</title>
  </head>
  <body>
    <Header />
    <h1>{pageTitle}</h1>
  </body>
</html>

正如你在上面的片段中所看到的,你可以在代码栅栏内定义本地JavaScript变量,然后使用类似JSX的表达式将变量注入HTML模板中。

现在在你的其他页面比如about.astro等,可以做同样的事情。

当你查看不同页面时,你可能又开始注意到一些恼人的东西。是的,当你在不同的页面中写同样的东西时,你会重复自己。除了标题之外,你的页面中所有的代码都是完全一样的。

我想这是谈论Astro布局的一个好时机。

Astro布局

Astro布局只是具有不同名称的Astro组件,用于创建一个UI结构或布局,比如一个页面模板。因此,任何你能在组件中做到的事情,都有可能在布局中实现。

你可以把你的布局文件放在你项目的任何地方,但把它们添加到src/layouts目录中是很好的做法。

在我们的项目中,有一些跨页面的共享标记可以作为模板使用,以避免在不同的文件中重复它们。为了做到这一点,让我们在 src/layouts目录中创建一个 BaseLayout.astro 文件。

我们把index.astro的内容复制粘贴到该文件中:

image.png

你刚刚完成了你的第一个Astro布局,现在你需要在你的Astro页面中使用它。让我们看看你如何能做到这一点。

像组件一样,第一步是将布局导入到代码栅栏,然后通过在模板部分放置其标签来使用它。下面就是index.astro的样子:

---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout></BaseLayout>

如果你试图为你的About页面做同样的事情,你会注意到about.astro里面有不同的内容。你需要保留它,或者以某种方式将它传递给你的BaseLayout文件。这就是<slot />的用武之地。

元素

<slot />元素是一个外部HTML内容的占位符。它指定了其他文件中的子元素应该被注入你的组件模板的位置。

你可以把这个元素添加到你的BaseLayout.astro文件中,就像下面的代码:

---
import Header from '../components/Header.astro';
const pageTitle = 'Bejamas';
---
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <title>{pageTitle}</title>
  </head>
  <body>
    <Header />
    <h1>{pageTitle}</h1>
    <slot /> <!-- your content is injected here -->
  </body>
</html>

现在,About页面的内容可以像这样放在BaseLayout标签之间:

---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout>
  <p>Jamstack development agency.</p>
</BaseLayout>

如果你查看你的浏览器,你会看到这两个页面是如何使用相同的模板但内容不同的。

只有一个部分被我们弄乱了,就是页面的标题。在我的例子中,两个标题都是 "Bejamas"。

这里就是组件props的用武之地!

Astro组件props

除了插槽,Astro组件的另一个特性是props,它在布局中可能非常有用。任何Astro组件都可以定义和接收props。要定义模板部分以外的props,你可以通过Astro.props全局设置。

在我们的例子中,我们可以定义一个pageTitle参数,并把它传递给我们的BaseLayout组件,以便能够在不同的页面上有不同的页面标题。

下面是你如何在BaseLayout组件中定义一个prop的例子:

---
import Header from '../components/Header.astro';
const { pageTitle } = Astro.props;
---
<html lang="en">
  <head>
    <title>{pageTitle}</title>
  </head>
  <body>
    <Header />
    <h1>{pageTitle}</h1>
    <slot /> <!-- your content is injected here -->
  </body>
</html>

注意我们是如何使用结构化语法从全局的Astro.props对象中取出props的。如果你有更多的props,你可以使用逗号分隔,就像下面这样:

const { pageTitle, pageDescription } = Astro.props;

现在,让我们看看你如何将一个prop传递到组件或者布局中。

index.astro页面可以将pageTitle作为属性进行传递:

---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout pageTitle="Bejamas"></BaseLayout>

此外,你可以在脚本中定义变量更易于管理。在About页面中这样做:

---
import BaseLayout from '../layouts/BaseLayout.astro';
const pageTitle = 'About';
---
<BaseLayout pageTitle={pageTitle}>
  <p>Jamstack development agency.</p>
</BaseLayout>

目前为止,我还没给你展示任何结果。原因是我们还缺少样式。那么我们就加一些CSS吧。

Astro中的样式

Astro项目可以用很多方法进行样式声明,我们在这里无法涵盖所有。然而你应该知道,Astro支持任何你能想到的方法。你可以编写纯CSS、Sass和CSS模块,甚至可以导入你喜欢的CSS库,比如Tailwind。

你可以直接在你的组件或页面模板上添加一个<style>标签。

---

---
<style>
  .container { /*  */  }
  
  nav {
    display: flex;
    gap: 1rem;    
  }

  nav a { /* */ }
</style>
<header>
  <div class="container">
    <a class="logo" href="/">
      <svg><!-- SVG Logo goes here --></svg></a>
    <nav>
      <a href="/">Home</a>
      <a href="/about">About</a>
    </nav>
  </div>
</header>

Astro <style> CSS规则默认是在组件内起作用和封装的。这意味着写在这个组件中的样式不会泄漏,也不会影响你网站的其他部分。

除了Header组件外,我将把其余的样式添加到一个外部的CSS文件中,并在项目中作为全局样式导入。

image.png

下面是你如何将外部的CSS文件导入到BaseLayout.astro文件中的例子:

---
import Header from '../components/Header.astro';
import '../styles/global.css';
const { pageTitle } = Astro.props;
---
<html lang="en">
  <head>
    <title>{pageTitle}</title>
  </head>
  <body>
    <Header />
    <h1>{pageTitle}</h1>
    <slot />
  </body>
</html>

在我跳到下一节之前,我将在这里分享一个工作demo。我给我的HomeAbout页面添加了一些静态内容,并写了一些样式。

下面是我添加到我的主页的内容:

---
  import BaseLayout from '../layouts/BaseLayout.astro';
  const pageTitle = 'Bejamas';
---
<BaseLayout pageTitle={pageTitle}>

  <section class="section">
    <div class="container">
      <div class="banner">
        <div class="">
          <h3 class="pretitle">Jamstack Developers for hire</h3>
          <h1 class="title">We build<br><mark>fast sites &amp; apps.</mark></h1>
          <p class="text">Maximize your business potential...</p>
          <a class="button" href="">Start project</a>
        </div>
        <img src="jam.svg" alt="" />
      </div>
    </div>
  </section>
  
</BaseLayout>

主页看起来长这样:

image.png

点击这里查看demo。

获取数据

我们教程的这一部分,我们将使用Bejamas API从服务器获取一些数据,并在我们的主页上创建这些案例研究卡。

在Astro中获取数据是非常容易的。你可以在你的代码栅栏中使用全局fetch()函数,在你的所有组件中向API发出HTTP请求。

index.astro中,我将添加这段代码,使用fetch()函数从服务器上获取案例研究的数据:

---
  import BaseLayout from '../layouts/BaseLayout.astro';
  const pageTitle = 'Bejamas';
  const response = await fetch('bejamas.io/api/blog?category=case-studies');
  const data = await response.json();
  const posts = data.posts;
---

现在我有了posts变量中的数据,我可以用它来生成动态HTML,在我的主页上显示案例研究卡片。

下面是posts数组的样子:

"posts": [
  {
    "excerpt": "",
    "mainImage": {
      "asset": {
        "url": ""
      }
    },
    "slug": "",
    "title": ""
  }
]

我会使用map函数遍历posts,然后动态创建每张卡片:

<section class="section" id="casestudies-section">
  <div class="container">
    <h2 class="section-title">Case studies</h2>
    <ul class="case-studies">
      {posts.map((post) => (
        <li>
          <article class="casestudy">
            <img src={post.mainImage.asset.url} alt="" />
            <div>
              <h3>{post.title}</h3>
              <p>{post.excerpt}</p>
              <a href={`https://bejamas.io/blog/${post.slug}`} class="">Read more</a>
            </div>
          </article>
        </li>
      ))}
    </ul>
  </div>
</section>

最酷的是,所有这些都是在构建时发生的,我们将只向浏览器发送静态HTML。

这是向全局CSS添加样式后的结果:

image.png

点击这里查看demo。

管理内容

当涉及到创建和管理你的内容时,Astro给你两个选择:

  • Markdown
  • MDX

MDX类似于标准的Markdown,但有额外的功能。它允许你在你的Markdown内容中使用变量、JSX表达式和组件。

Astro内置了对Markdown的支持,但为了处理.mdx文件,你需要安装@astrojs/mdx进行集成。在本教程中,我们坚持使用标准的Markdown内容。

在我们进一步讨论之前,有必要提到Astro v2引入了内容集合,这是一种在Astro项目中组织内容的绝佳方式。我们将在未来的教程中写更多关于这个主题的内容。

正如我们前面所说的,由于静态路由在Astro中的工作方式,src/pages/目录中的任何页面都会得到一个路由。这意味着你可以在你的浏览器中打开它,或者在你的项目中的任何地方链接到它。另外,我们知道Markdown文件是Astro的一种页面类型,我们可以把它放在这个目录里面。牢记这些信息,让我们在 src/pages 目录中创建我们的第一个内容。

为了更有条理,我创建了一个blog文件夹,把我的.md文件放在那里,并把我的第一个Markdown内容添加到其中:

image.png

由于src/pages目录下的Astro组件(.astro)和Markdown文件(.md)会自动成为你网站上的页面,你可以简单地导航到以下URL,访问你的第一篇博文:

localhost:3000/blog/jamstack

你可以在你的Markdown的前言中添加更多关于你内容的信息,比如它的标题,发布日期,主要图片等等,就像下面这样:

---
title: 'Jamstack Explained'
pubDate: 2020-12-14
description: 'Jamstack is not about a specific technology…'
author: 'Denis Kostrzewa'
image:
    url: '<https://bejamas.io/_next/image/?.>..' 
    alt: 'Jamstack Explained Photo'
---

# Jamstack Explained
Jamstack is no longer a buzzword over which dev keyword warriors brawl. It has grown to become a booming ecosystem of tools helping developers ship performant websites, progressive web apps, and other projects with benefits too good to ignore.

你当然不希望你的文章看起来像这样,肯定希望把你的网站设计融入其中,对吗?让我们为我们的博客内容创建一个布局。

src/layouts目录下添加一个名为BlogLayout.astro的文件,并将以下代码复制并粘贴到其中:

---
import Header from '../components/Header.astro';
import '../styles/global.css';
const { frontmatter } = Astro.props;
---
<html lang="en">
  <head>
  </head>
  <body>
    <Header />
    <div class="container">
      <div class="meta">
        <div>    
          <time class="date">{frontmatter.pubDate.slice(0, 10)}</time>
          <h1 class="title">{frontmatter.title}</h1>
          <p class="description">{frontmatter.description}</p>
          <span class="author">Author: <span class="author-name">{frontmatter.author}</span></span>
        </div>
        <img class="poster" src={frontmatter.image.url}  alt={frontmatter.image.alt} />
      </div>  
      <div class="body">
        <slot />
      </div>
    </div>
  </body>
</html>

请注意我们是如何使用Astro.props将frontmatter属性传递给这个布局的。现在你可以以任何方式将这些属性添加到你的模板中。

另外,注意插槽元素。这是内容出现在最终HTML页面上的地方。

还有一步。我们需要把这个布局添加到我们的内容中,所以我们回到我们的第一个Markdown文件,像以下代码那样做:

---
layout: ../../layouts/BlogLayout.astro
title: 'Jamstack Explained'
pubDate: 2020-12-14
description: 'Jamstack is not about a specific technology…'
author: 'Denis Kostrzewa'
image:
    url: '<https://bejamas.io/_next/image/?.>..' 
    alt: 'Jamstack Explained Photo'
---

# Jamstack Explained
Jamstack is no longer a buzzword over which dev keyword warriors brawl. It has grown to become a booming ecosystem of tools helping developers ship performant websites, progressive web apps, and other projects with benefits too good to ignore.

正如你在第一行代码中所看到的,Astro有一个特殊的layout属性用于Markdown页面。这个属性定义了一个Astro布局组件的相对路径。

localhost:3000/blog/jamstack再次预览,看看布局给你的页面添加了什么。

嵌套布局

你是否注意到,我们不得不在我们的BlogLayout.astro布局中添加<head><body>标签?难道我们不能直接使用我们的BaseLayout来做这个吗?

因为Astor布局基本上是组件,那么我们可以嵌套它们。所以我们需要做的就是把我们的BaseLayout添加到新的BlogLayout.astro文件中:

---
import BaseLayout from "./BaseLayout.astro";
const { frontmatter } = Astro.props;
---

<BaseLayout pageTitle={frontmatter.title}>
  <div class="container">
    <div class="meta">
      <div>    
        <time class="date">{frontmatter.pubDate.slice(0, 10)}</time>
        <h1 class="title">{frontmatter.title}</h1>
        <p class="description">{frontmatter.description}</p>
        <span class="author">Author: <span class="author-name">{frontmatter.author}</span></span>
      </div>
      <img class="poster" src={frontmatter.image.url}  alt={frontmatter.image.alt} />
    </div>  
    <div class="body">
      <slot />
    </div>
  </div>
</BaseLayout>

多么整洁,不是吗?

另外,注意到我们是如何将我们页面的标题传递给BaseLayout中的页面标题的:

<BaseLayout pageTitle={frontmatter.title}>

让我们给BlogLayout添加一些样式,我将在BlogLayout.astro文件中添加作用域内的样式:

---
import BaseLayout from "./BaseLayout.astro";
const { frontmatter } = Astro.props;
---

<style>
  .container {
    padding: 3rem 0;
    max-width: 1152px;
  }

  .meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 2rem;
  }

  /* And more... */
</style>

<BaseLayout pageTitle={frontmatter.title}>
  <!-- ... -->
</BaseLayout>

现在页面看起来长这样:

image.png

我们需要做的最后一件事是在我们的主页上显示这些文章。

加载本地文件

在你的blog目录中添加更多的博客文章,这样我们就可以在我们的主页上创建一个列表。

Astro.glob()允许你将本地文件加载到你的静态页面上。它将返回一个对象数组,每个博客文章都有一个,包含所有关于你的Markdown文件的信息。

下面是你如何在你的index.astro文件中使用它:

---
  const blogs = await Astro.glob('../pages/blog/*.md');
---

为了动态地生成整个文章列表,我们对Astro.glob()返回的博客数组进行map遍历,如以下代码:

<section class="section blog-section" id="blog-section">
  <div class="container">
    <h2 class="section-title">Our Blog</h2>
    <ul class="blogs">
      {blogs.map((blog) =>
        <li>
          <article class="blog">          
            <img src={blog.frontmatter.image.url} alt="blog.frontmatter.image.alt" />
            <h3>{blog.frontmatter.title}</h3>
            <p>{blog.frontmatter.description}</p>
            <a href={blog.url} class="">Read more</a>
          </article>            
        </li>
      )}
    </ul>
  </div>
</section>

我们在index.astro文件中的案例研究部分下面添加了这个文件。

在浏览器中重新审视你的主页,享受你在页面底部添加的博客文章列表。在向global.css添加一些样式后,页面看起来是这样的:

image.png

如果你点击”Read more”链接,你会看到每篇文章的内容。

这里是目前为止项目的demo。

添加脚本

你可以使用标准的HTML <script>标签向你的Astro组件添加交互。这允许你发送JavaScript到浏览器中运行,并为你的Astro组件添加功能。例如,对于切换明亮模式到暗黑模式,你不需要一个JavaScript框架,你可以用普通的JavaScript来处理它。

.astro文件中,你可以用与HTML文件相同的标准方式添加客户端JavaScript:

<script>
  console.log('Print this to the browser console');
</script>

<!-- relative path to script at `src/scripts/local.js` -->
<script src="../scripts/local.js"></script>

<!-- also works for local TypeScript files -->
<script src="./script-with-types.ts"></script>

<script is:inline src="<https://my-extenrnal-script.com/script.js>"></script>

你添加的所有脚本将被处理并捆绑在Astro中,然后用type="module"注入到页面的<head>中。

如果你想避免捆绑脚本,你可以使用is:inline指令导入一个外部文件,就像例子中最后一个那样。

使用UI框架

Astro最引人注目的特点之一是它可以灵活地与你喜欢的JS框架集成。而且你不必只使用一个框架,你可以使用多个。

在我们的项目中,我想在主页的底部添加一个FAQ部分。我没有太多的时间,只想使用别人的作品,以便能够尽快创建我的页面。我搜索了一下FAQ的React组件,出现了一些链接。

那么问题来了,如何将React组件添加到你的项目中。

首先,你需要将React添加到你的项目中。在你的终端运行以下命令:

npx astro add react

你可以简单地在你的项目中编写自己的React组件,在src/components目录下添加一个.jsx文件。

由于我想导入一个React组件而不是自己写,所以我需要先把它添加到我的项目中。

所以我将用我的终端来安装这个包:

npm install react-faq-component

我将把FAQ.jsxFAQ.css文件添加到components目录中,并对我所导入的组件进行自定义:

import React, { useEffect, useState } from 'react';
import Faq from 'react-faq-component';
import './FAQ.css';

const data = {
  rows: [],
};

const styles = {};

const config = {};

export default function FAQ() {
  return <div>
            <Faq
                data={data}
                styles={styles}
                config={config}
            />
        </div>;
}

你的组件一旦准备就绪,你就需要将其导入到页面中:

---
  import BaseLayout from '../layouts/BaseLayout.astro';
  import Faq from '../components/FAQ.jsx';
  const pageTitle = "Bejamas";
---

接着在模板中随心所欲地使用:

<section class="section" id="faq-section">
  <h2 class="section-title">Questions you probably want to ask</h2>
  <div class="container faq-container">
    <Faq />
  </div>
</section>

下面是最终效果:

image.png

如果你在浏览器中进行查看,你会注意到该组件已经在你的页面上呈现了。然而它没有任何可交互性。由于动作不生效,当你点击按钮时,你无法展开子项。

我将在下一节向你展示我们需要的东西。

指令

正如你在上一个例子中看到的,这个组件被添加到了页面上,但它没有生效。发生这种情况是因为,默认情况下,你的框架组件只会在服务端渲染为静态HTML,所以,你的点击处理器或状态钩子就不会生效。这对于添加非交互式的组件非常有用,可以避免向客户端发送任何不必要的JavaScript。

你可以通过添加Astro指令使一个框架组件具有交互性(hydrated)。这些组件属性指明组件的JavaScript何时应该被发送到浏览器。

我在这里罗列出一些Astro的指令:

  • <Faq client:load /> 在页面加载时渲染该组件。
  • <Faq client:idle /> 一旦浏览器有空闲时间,就会渲染该组件。
  • <Faq client:visible /> 只有当该组件被滚动到视口范围中时才会渲染。
  • <Faq client:media="{media query here}" />只有在媒体查询生效的情况下才会渲染该组件。
  • <Faq client:only="react" /> 只在客户端渲染该组件,而不会在服务端渲染成静态HTML。

如果你不像上一个例子那样给你的组件添加任何这些东西,该组件的纯HTML版本将在浏览器中渲染,所以任何点击处理器或状态都不会生效。

我想在页面加载时加载我的FAQ组件,所以这就是我需要的:

<Faq client:load />

请注意,所有这些都来自于Astro中的Island Architecture

最后,这是我们的最终效果

构建和发布

Astro网站是开箱即用型的静态网站。这意味着所有的页面在最后都是静态HTML。因此,如果你拥有一台服务器,你部署网站的第一个选择是仅将你的最终HTML文件上传到你的服务器。

在你部署你的网站之前,你需要构建它。要做到这一点,你需要从你的Astro项目的根目录中运行构建命令。你可以通过在你的终端运行以下命令来做到这一点:

npm run build

项目的最终构建将被默认存储在dist文件夹中。所以,你需要做的就是把你的dist目录上传到你的服务器。 手动部署你的网站不是现在的首选方法。有大量的工具和服务可以为你自动完成整个工作流程。你所需要做的就是推送你的变化,他们将为你构建和部署项目。

你可以按照Astro网站上的指南,看看你如何在不同的部署服务上部署你的项目,如Netlify、Vercel、Deno等。

总结

总之,作为网络开发者,JavaScript框架的兴起赋予了我们诸多力量和丰富的体验。我们喜欢使用这些框架,因为它们使创建组件、共享和重用它们变得很容易。围绕使用Vue、React和Svelte等框架进行构建的工具是一流的。然而,使用这些框架的代价往往是在我们的页面上发送大量的JavaScript,即使是简单的静态内容。

有了Astro,我们就能得到两者的好处。我们仍然可以使用JSX和JavaScript编写动态内容,但Astro将其全部渲染成静态HTML,所以我们只加载我们真正需要的JavaScript。这样一来,我们的用户就有了快速、无缝的体验,而我们仍然可以享受到使用动态框架工作的所有好处。这对用户和开发者来说是一个双赢的局面!

以上就是本文的全部内容,如果对你有所帮助,欢迎点赞、收藏、转发~

与从零开始使用 Astro 的实用指南相似的内容:

从零开始使用 Astro 的实用指南

在这个实用的Astro指南中,我将指导你完成设置过程,并告诉你如何构造你的文件。你将学习如何添加页面、交互式组件,甚至是markdown文章。我还会告诉你如何从服务器上获取数据,创建布局,并使用vanilla JavaScript和其他框架添加互动性。准备好享受一些动手的乐趣,因为我们将一起创建一个

Python Django 零基础从零到一部署服务,Hello Django!全文件夹目录和核心代码!

**在这篇文章中,我将手把手地教你如何从零开始部署一个使用Django框架的Python服务。无论你是一个刚开始接触开发的新手,还是一个有经验的开发者想要快速了解Django,这篇教程都会为你提供一条清晰的路径。我们将从环境搭建开始,一步一步地创建一个可以处理GET和POST请求的服务,让你能在实践

从零开始写 Docker(十五)---实现 mydocker run -e 支持环境变量传递

本文为从零开始写 Docker 系列第十五篇,实现 mydocker run -e, 支持在启动容器时指定环境变量,让容器内运行的程序可以使用外部传递的环境变量。 完整代码见:https://github.com/lixd/mydocker 欢迎 Star 推荐阅读以下文章对 docker 基本实现

[转帖]从零开始学nginx

1. nginx简介 nginx(发音同engine x)是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like协议下发行。 nginx由俄罗斯的程序设计师Igor Sysoev所开发,最初供俄国大型的入口网站及搜寻引擎Rambler使用。 第

Go-Zero从0到1实现微服务项目开发(二)

继续更新GoZero微服务实战系列文章:上一篇被GoZero作者万总点赞了,本文将继续使用 Go-zero 提供的工具和组件,从零开始逐步构建一个基本的微服务项目。手把手带你完成:项目初始化+需求分析+表结构设计+api+rpc+goctl+apifox调试+细节处理。带你实现一个完整微服务的开发。

从零开始写 Docker(十四)---重构:实现容器间 rootfs 隔离

本文为从零开始写 Docker 系列第十四篇,实现容器间的 rootfs 隔离,使得多个容器间互不影响。 完整代码见:https://github.com/lixd/mydocker 欢迎 Star 推荐阅读以下文章对 docker 基本实现有一个大致认识: 核心原理:深入理解 Docker 核心原

从零开始写 Docker(十三)---实现 mydocker rm 删除容器

本文为从零开始写 Docker 系列第十三篇,实现类似 docker rm 的功能,使得我们能够删除容器。 完整代码见:https://github.com/lixd/mydocker 欢迎 Star 推荐阅读以下文章对 docker 基本实现有一个大致认识: 核心原理:深入理解 Docker 核心

从零开始写 Docker(十二)---实现 mydocker stop 停止容器

本文为从零开始写 Docker 系列第十二篇,实现类似 docker stop 的功能,使得我们能够停止指定容器。 完整代码见:https://github.com/lixd/mydocker 欢迎 Star 推荐阅读以下文章对 docker 基本实现有一个大致认识: 核心原理:深入理解 Docke

如何发布一个 TypeScript 编写的 npm 包

前言 在这篇文章中,我们将使用TypeScript和Jest从头开始构建和发布一个NPM包。 我们将初始化一个项目,设置TypeScript,用Jest编写测试,并将其发布到NPM。 项目 我们的库称为digx。它允许从嵌套对象中根据路径找出值,类似于lodash中的get函数。 比如说: cons

使用小波分析和深度学习对心电图 (ECG) 进行分类 mcu-ai低成本方案 mcu-ai低成本方案

具体的软硬件实现点击 http://mcu-ai.com/ MCU-AI技术网页_MCU-AI人工智能 此示例说明如何使用连续小波变换 (CWT) 和深度卷积神经网络 (CNN) 对人体心电图 (ECG) 信号进行分类。 从头开始训练深度 CNN 的计算成本很高,并且需要大量的训练数据。在很多应用中