在这个实用的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的小型对话:
一旦你在编辑器中打开你的项目,你可以安装Astro的扩展。由于Astro有自己的文件扩展和语法,你可能想为你的编辑器安装其扩展。这里是VSCode的Astro扩展的链接,它不仅仅为你高亮语法,还能做得更多。
现在你可以用以下命令来运行你的项目。不需要安装任何依赖。
npm run dev
打开浏览器,访问http://localhost:3000/ ,一切就绪。
Astro项目结构
Astro的文件结构相当直截了当。
src
:你的源码(组件、页面、样式等等)public
:你的静态资源(字体、图标等等)
在src/pages
目录下,Astro创建了一个index.astro
,你可以认为这是index.html
。
值得注意的是,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.astro
和about.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
的内容复制粘贴到该文件中:
你刚刚完成了你的第一个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文件中,并在项目中作为全局样式导入。
下面是你如何将外部的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。我给我的Home
和About
页面添加了一些静态内容,并写了一些样式。
下面是我添加到我的主页的内容:
---
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 & 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>
主页看起来长这样:
点击这里查看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添加样式后的结果:
点击这里查看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内容添加到其中:
由于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>
现在页面看起来长这样:
我们需要做的最后一件事是在我们的主页上显示这些文章。
加载本地文件
在你的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
添加一些样式后,页面看起来是这样的:
如果你点击”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.jsx
和FAQ.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>
下面是最终效果:
如果你在浏览器中进行查看,你会注意到该组件已经在你的页面上呈现了。然而它没有任何可交互性。由于动作不生效,当你点击按钮时,你无法展开子项。
我将在下一节向你展示我们需要的东西。
指令
正如你在上一个例子中看到的,这个组件被添加到了页面上,但它没有生效。发生这种情况是因为,默认情况下,你的框架组件只会在服务端渲染为静态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。这样一来,我们的用户就有了快速、无缝的体验,而我们仍然可以享受到使用动态框架工作的所有好处。这对用户和开发者来说是一个双赢的局面!