如何使用Next.js创建动态的Rick and Morty Wiki Web App
Building web apps with dynamic APIs and server side rendering are a way to give people a great experience both with content and speed. How can we use Next.js to easily build those apps?
使用动态API和服务器端渲染来构建Web应用程序是一种使人们在内容和速度上都获得出色体验的方法。 我们如何使用Next.js轻松构建那些应用程序?
What are we going to build?
我们要建造什么?
What is Next.js?
什么是Next.js?
Step 0: Setting up a new Next.js app
步骤0:建立新的Next.js应用程式
Step 1: Fetching Rick and Morty characters with an API in Next.js
步骤1:在Next.js中使用API提取Rick和Morty字符
Step 2: Displaying Rick and Morty characters on the page
步骤2:在页面上显示Rick和Morty字符
Step 3: Loading more Rick and Morty characters
步骤3:载入更多Rick and Morty角色
Step 4: Adding the ability to search for Rick and Morty characters
步骤4:新增搜寻Rick和Morty角色的功能
Step 5: Using dynamic routes to link to Rick and Morty character pages
步骤5:使用动态路由链接到Rick和Morty角色页面
Bonus Step: Deploy your Rick and Morty wiki to Vercel!
奖励步骤:将Rick and Morty Wiki部署到Vercel!
我们要建造什么? (What are we going to build?)
We’re going to have some fun and build out a web app that serves as a basic wiki for Rick and Morty characters.
我们将获得一些乐趣,并构建一个Web应用程序,作为Rick和Morty角色的基本Wiki。
Our app is going to consist of a few things:
我们的应用将包含以下几项内容:
- A list of characters on the front page首页上的字符列表
- A button that can load more characters, as the API is paginated在分页API时可以加载更多字符的按钮
- A search box to look up characters搜索框以查找字符
- A character page with basic details带有基本详细信息的字符页面
We’ll learn some concepts like:
我们将学习一些概念,例如:
How to spin up a web app with Next.js
如何使用Next.js启动Web应用程序
How to fetch and use data from an API
如何从API获取和使用数据
How to pre-render data from an API
如何从API预渲染数据
How to set up dynamic routing
如何设置动态路由
什么是Next.js? (What is Next.js?)
Next.js is a React framework from Vercel. It let’s you easily build lightweight dynamic web apps with a ton of modern features you’d expect out-of-the-box.
Next.js是Vercel的React框架。 它使您可以轻松地构建具有大量现成可用的现代功能的轻量级动态Web应用程序。
Vercel, the company that supports Next.js, is a service that allows you to automate continuous development pipelines to easily deploy web apps to the world. We’ll also use Vercel’s command line tool to optionally deploy our new wiki demo.
支持Next.js的公司Vercel是一项服务,可让您自动执行持续的开发流程,以轻松地将Web应用程序部署到全世界。 我们还将使用Vercel的命令行工具来选择性地部署我们的新Wiki演示。
步骤0:建立新的Next.js应用程式 (Step 0: Setting up a new Next.js app)
To get started, let’s spin up our Next.js project. We’ll use npm or yarn to get started:
首先,让我们启动Next.js项目。 我们将使用npm或yarn开始:
yarn create next-app
# or
npx create-next-app
Once you run that command, it will ask you a few questions. I’m going to call my project my-rick-and-morty-wiki
, but you can name it whatever you’d like.
一旦运行该命令,它将询问您几个问题。 我将我的项目称为my my-rick-and-morty-wiki
,但是您可以根据需要命名。
It will then ask you which template to choose — go ahead and select the default template.
然后它将询问您要选择哪个模板-继续并选择默认模板。
Finally, it will install all of the dependencies.
最后,它将安装所有依赖项。
When it’s finished, you can navigate to that new directory and run:
完成后,您可以导航到该新目录并运行:
yarn dev
# or
npm run dev
You should now have a local server running at http://localhost:3000!
您现在应该在http:// localhost:3000上运行本地服务器!
步骤1:在Next.js中使用API提取Rick和Morty字符 (Step 1: Fetching Rick and Morty characters with an API in Next.js)
Now that we have our app set up, the first thing we need to actually build out our wiki is a list of characters.
既然我们已经设置了应用程序,那么实际构建Wiki所需的第一件事就是字符列表。
To do this, we’re going to start off in our home page in pages/index.js
.
为此,我们将在我们的首页pages/index.js
。
Next.js scaffolds this page for us automatically. It’s the first page someone will hit on our website and has some basic features in the default template like a title, a simple grid, and some styles.
Next.js会自动为我们搭建此页面。 这是某人会在我们网站上访问的第一页,并且默认模板具有一些基本功能,例如标题,简单的网格和某些样式。
Currently, this page isn’t requesting any data. To get our characters, we’re going to jump right into requesting this server side.
当前,此页面未请求任何数据。 为了获得角色,我们将直接进入请求此服务器端的操作。
To do this, Next.js allows us to export an async getServerSideProps
function right next to our page, which it will use to inject our page with any data that we fetch.
为此,Next.js允许我们在页面旁边导出一个异步getServerSideProps
函数,它将使用该函数将获取的所有数据注入页面。
Let’s start off by adding the following snippet above our Home
function component:
首先,在Home
函数组件上方添加以下代码段:
const defaultEndpoint = `https://rickandmortyapi.com/api/character/`;export async function getServerSideProps() {const res = await fetch(defaultEndpoint)const data = await res.json();return {props: {data}}
}
Here’s what we’re doing:
这是我们正在做的:
We’re setting a variable called
defaultEndpoint
that simply defines our default API endpoint我们正在设置一个名为
defaultEndpoint
的变量,该变量仅定义了我们的默认API端点We’re defining our
getServerSideProps
function that we’ll use to fetch our data我们正在定义用于获取数据的
getServerSideProps
函数In that function, we first use the
fetch
API to make a request to our endpoint在该函数中,我们首先使用
fetch
API向端点发出请求With it’s response, we run the
json
method so that we can grab the output in JSON format有了它的响应,我们运行
json
方法,以便我们可以获取JSON格式的输出Finally, we return an object where we make our
data
available as a prop in theprops
property最后,我们返回一个对象,在该对象中,我们可以在
props
属性中将data
作为prop
Now that we’re making that request, we need to make it available to use.
现在,我们正在发出该请求,我们需要使其可用。
Our data
is made available as a prop, so let’s create an argument in our Home
component function to grab that:
我们的data
可以作为道具使用,因此让我们在Home
组件函数中创建一个参数来抓取该参数:
export default function Home({ data }) {
To test this, we can use console.log
to see the results:
为了测试这一点,我们可以使用console.log
查看结果:
export default function Home({ data }) {console.log('data', data);
And once we save and reload the page, we can now see our results!
保存并重新加载页面后,我们现在可以看到结果!
Follow along with the commit!
跟随提交!
步骤2:在页面上显示Rick和Morty字符 (Step 2: Displaying Rick and Morty characters on the page)
Now that we have our character data, let’s actually display it on our page.
现在我们有了字符数据,让我们实际在页面上显示它。
To start, I’m going to make a few tweaks. I’m going to update:
首先,我将进行一些调整。 我要更新:
The
<h1>
title to “Wubba Lubba Dub Dub!”<h1>
标题为“ Wubba Lubba Dub Dub!”The
<p>
description to “Rick and Morty Character Wiki”“ Rick and Morty Character Wiki”的
<p>
描述
I’m also going to update the contents of <div clasName=“grid”
to:
我还将将<div clasName=“grid”
的内容更新为:
<ul className="grid"><li className="card"><a href="https://nextjs.org/docs"><h3>My Character</h3></a></li>
</ul>
What I’m doing here:
我在这里做什么:
I’m making the
<div>
a list as that will be better for accessibility我将
<div>
列为列表,因为这样会更好地实现可访问性I’m making the
<li>
of the<ul>
thecard
我正在制作
<ul>
card
的<li>
And just changing the
<h3>
to “My Character” temporarily并将
<h3>
临时更改为“我的角色”
To make sure our new <ul>
doesn’t mess up the layout with it’s default styles, let’s also add the following to the bottom of the .grid
CSS rules:
为了确保我们的新<ul>
不会使用默认样式弄乱布局,我们还要在.grid
CSS规则的底部添加以下内容:
list-style: none;
margin-left: 0;
padding-left: 0;
And now if we look at the page, we should see our basic changes.
现在,如果我们看一下页面,我们应该看到我们的基本更改。
Next, let’s make our grid load our characters.
接下来,让我们的网格加载角色。
At the top of our Home
component function, let’s add:
在我们的Home
组件函数的顶部,让我们添加:
const { results = [] } = data;
That will destructure our results array from our data object.
这将从我们的数据对象中破坏结果数组。
Next, let’s update our grid code:
接下来,让我们更新网格代码:
<ul className="grid">{results.map(result => {const { id, name } = result;return (<li key={id} className="card"><a href="#"><h3>{ name }</h3></a></li>)})}
</ul>
Here’s what we’re doing:
这是我们正在做的:
We’re using the
map
method to create a new list element for each of our results (or characters)我们正在使用
map
方法为每个结果(或字符)创建一个新的list元素Inside of that, we’re grabbing the
id
andname
from each character result在其中,我们从每个字符结果中获取
id
和name
We’re using the ID as a
key
for our list element to make React happy我们将ID用作列表元素的
key
,以使React开心We’re updating our header with the
name
我们将标题更新
name
And once you save and reload the page, we should now see a new list of our characters from the API!
保存并重新加载页面后,我们现在应该从API中看到一个新的字符列表!
We can also add an image for each character.
我们还可以为每个字符添加一个图像。
First, inside of our grid, let’s update our destructure statement to grab the image URL:
首先,在网格内部,让我们更新分解结构语句以获取图像URL:
const { id, name, image } = result;
Next, let’s add the image above our header:
接下来,让我们在标题上方添加图片:
<img src={image} alt={`${name} Thumbnail`} />
And now each of our characters also shows their picture!
现在我们的每个角色也都展示了自己的照片!
Follow along with the commit!
跟随提交!
步骤3:载入更多Rick and Morty角色 (Step 3: Loading more Rick and Morty characters)
Now if you notice, when we load the page, we only get a certain number of results. By default, the API won’t return the entire list of characters, which makes sense, because it’s really long!
现在,如果您注意到,在加载页面时,我们只会得到一定数量的结果。 默认情况下,API不会返回整个字符列表,这很有意义,因为它真的很长!
Instead, it uses pagination and provides us with the “next” endpoint, or the next page of results, that will allow us to load in more results.
相反,它使用分页并为我们提供“下一个”端点或结果的下一页,这将使我们能够加载更多结果。
To start, we’re going to use React’s useState
hook to store our results in state. We’ll then have the ability to update that state with more results.
首先,我们将使用React的useState
挂钩将结果存储在状态中。 然后,我们将能够用更多结果更新该状态。
First, let’s import useState
from React:
首先,让我们从React导入useState
:
import { useState } from 'react';
Next, let’s create our state by first renaming our original results
variable and setting up our useState
instance:
接下来,让我们通过首先重命名原始results
变量并设置我们的useState
实例来创建状态:
const { results: defaultResults = [] } = data;
const [results, updateResults] = useState(defaultResults);
If you save that and reload the page, you shouldn’t notice anything different yet.
如果保存并重新加载页面,则不会有任何不同。
Next, we want to be able to understand in our application what our current endpoint we’ve made a request is, what the next endpoint is, what the previous endpoint is, and how we can update all of that.
接下来,我们希望能够在应用程序中了解我们已请求的当前端点是什么,下一个端点是什么,上一个端点是什么以及如何更新所有端点。
To do this, we’re going to create more state. First, we want to update our destructuring statement with our data
to get the info
value:
为此,我们将创建更多状态。 首先,我们要使用data
更新解构语句以获取info
值:
const { info, results: defaultResults = [] } = data;
Next, let’s set up some state using that:
接下来,让我们使用它来设置一些状态:
const [page, updatePage] = useState({...info,current: defaultEndpoint
});
Here, we’re:
在这里,我们是:
Creating a new
page
state that we can use to get ourprev
andnext
values创建新
page
的状态,我们可以用它来获得我们的prev
和next
值We’re also creating a new value called
current
we’ll we start off by using ourdefaultEndpoint
, which was the request made on the server我们还将创建一个名为
current
的新值,我们将使用defaultEndpoint
,这是在服务器上发出的请求
The idea here, is when we want to load more results, we’re going set up code to watch the value of current
and update that value with the next
, so when it changes, we’ll make a new request.
这里的想法是,当我们想加载更多结果时,我们将设置代码以监视current
的值,并使用next
更新该值,因此当它更改时,我们将发出一个新请求。
To do that, let’s add a useEffect
hook to make that request:
为此,我们添加一个useEffect
挂钩来发出该请求:
const { current } = page;useEffect(() => {if ( current === defaultEndpoint ) return;async function request() {const res = await fetch(current)const nextData = await res.json();updatePage({current,...nextData.info});if ( !nextData.info?.prev ) {updateResults(nextData.results);return;}updateResults(prev => {return [...prev,...nextData.results]});}request();
}, [current]);
Here’s what’s going on:
这是怎么回事:
First, we’re destructuring the
current
value from `page首先,我们要从`page中解构
current
值We’re creating a
useEffect
hook that usescurrent
as a dependency. If they value changes, the hook will run我们正在创建一个
useEffect
挂钩,该挂钩使用current
作为依赖项。 如果它们的值更改,则挂钩将运行If our
current
value is the same asdefaultEndpoint
, we don’t run the code, as we already have our request data. Prevents and extra on load request如果我们的
current
值与defaultEndpoint
相同,则因为已有请求数据,所以我们不运行代码。 防止和额外的负载请求We create an async function that we’re able to run. This allows us to use
async/await
inside of ouruseEffect
hook我们创建一个能够运行的异步函数。 这使我们可以在
useEffect
挂钩中使用async/await
We make the request to the
current
endpoint. With that successful request, we update thepage
state with the newinfo
like the newprev
andnext
value我们向
current
端点发出请求。 与成功的请求,我们更新了page
用新状态info
,如新prev
和next
值- If our request does not have a previous value, that means it’s the first set of results for the given request, so we should completely replace our results to start from scratch如果我们的请求没有先前的值,则意味着它是给定请求的第一组结果,因此我们应完全替换结果以从头开始
- If we do have a previous value, concatenate our new results to the old, as that means we just requested the next page of results如果确实具有先前的值,则将我们的新结果连接到旧结果,因为这意味着我们只请求了下一页结果
Again, if you save and reload the page, this still shouldn’t do anything and your page should be where it was before.
同样,如果您保存并重新加载页面,则此操作仍然不应执行,并且您的页面应位于之前的位置。
Finally, we’re going to create a Load More button and use it to update the current
value to fire off a new request when we want a new page.
最后,我们将创建一个“加载更多”按钮,并使用它来更新current
值,以在需要新页面时触发新请求。
To do that, let’s first add a new button below our grid:
为此,我们首先在网格下方添加一个新按钮:
<p><button>Load More</button>
</p>
Now we want something to happen when we click that button, so first add an event handler:
现在,我们希望在单击该按钮时发生某些事情,因此首先添加一个事件处理程序:
<button onClick={handleLoadMore}>Load More</button>
Then above the component return statement, let’s add that function:
然后在组件return语句上方,添加该函数:
function handleLoadMore() {updatePage(prev => {return {...prev,current: page?.next}});
}
When triggered with our button click, this function will update our page
state with a new current
value, specifically with the next
value which is the endpoint to fetch our next page of results.
当单击按钮触发时,此函数将使用新的current
值(特别是next
值)来更新page
状态, next
值是获取下一页结果的端点。
And when we save and reload the page, it does just that!
当我们保存并重新加载页面时,它就完成了!
Follow along with the commit!
跟随提交!
步骤4:新增搜寻Rick和Morty角色的功能 (Step 4: Adding the ability to search for Rick and Morty characters)
One of the features out Rick and Morty API provides is the ability to filter results — so basically the ability to search. So let’s add that as a feature.
Rick and Morty API提供的功能之一是能够过滤结果-基本上就是搜索功能。 因此,我们将其添加为功能。
First, we need a search form. Let’s add the following snippet under the description paragraph:
首先,我们需要一个搜索表单。 让我们在description段落下添加以下代码段:
<form className="search"><input name="query" type="search" /><button>Search</button>
</form>
Next, let’s add these styles to the bottom of the first <style jsx>
block:
接下来,让我们将这些样式添加到第一个<style jsx>
块的底部:
.search input {margin-right: .5em;
}@media (max-width: 600px) {.search input {margin-right: 0;margin-bottom: .5em;}.search input,.search button {width: 100%;}
}
That’s going to give some spacing to our search input and button as well as make it mobile friendly. Feel free to add more styles if you’d like.
这将为我们的搜索输入和按钮留出一些空间,并使它易于移动。 如果需要,可以随意添加更多样式。
And if we save and refresh our page, we have a simple form.
而且,如果我们保存并刷新页面,我们将获得一个简单的表单。
It doesn’t do anything yet, so let’s make it search when submit the form.
它什么都没有做,所以让我们在提交表单时进行搜索。
To start, let’s add an onSubmit
attribute to our form:
首先,让我们在表单中添加onSubmit
属性:
<form className="search" onSubmit={handleOnSubmitSearch}>
And to go with that, let’s define our submit function above our return statement:
然后,让我们在return语句上方定义Submit函数:
function handleOnSubmitSearch(e) {e.preventDefault();const { currentTarget = {} } = e;const fields = Array.from(currentTarget?.elements);const fieldQuery = fields.find(field => field.name === 'query');const value = fieldQuery.value || '';const endpoint = `https://rickandmortyapi.com/api/character/?name=${value}`;updatePage({current: endpoint});
}
Here’s what we’re doing:
这是我们正在做的:
- First we’re preventing default behavior from the form submission to prevent the page from reloading首先,我们阻止表单提交的默认行为,以防止页面重新加载
- Next we grab the current target, which is our form接下来,我们获取当前目标,即我们的表单
- We grab the fields from the form by using the elements property. We also turn this into an array so it’s easy to work with我们使用elements属性从表单中获取字段。 我们还将其转换为数组,因此使用起来很容易
- We search those fields for our query input我们在这些字段中搜索查询输入
- We grab the value of that input我们获取该输入的价值
- We create a new endpoint where we filter by name using that query value我们创建一个新的端点,在其中使用该查询值按名称进行过滤
Finally, we update our
current
property in our page state to trigger a new request to that endpoint最后,我们在页面状态下更新
current
属性以触发对该端点的新请求
And once you save that and reload the page, you can now give search a try. You should be able to type in a name like “rick”, hit enter or click the search button, and you should now see filtered results with the various ricks across the universe!
保存并重新加载页面后,现在可以尝试搜索。 您应该能够输入“ rick”之类的名称,按Enter或单击“搜索”按钮,现在您应该可以看到过滤后的结果以及整个Universe中的各种rick!
Follow along with the commit!
跟随提交!
步骤5:使用动态路由链接到Rick和Morty角色页面 (Step 5: Using dynamic routes to link to Rick and Morty character pages)
Now that we have all of our characters, we want to be able to click into those characters and display some additional details. To do that, we’re going to make use of Next.js’s dynamic routes.
现在我们已经拥有所有字符,我们希望能够单击这些字符并显示一些其他详细信息。 为此,我们将利用Next.js的动态路由。
The first thing we need to do is properly configure our directory structure so Next.js recognizes the dynamic path. In order to set up a dynamic route, we need to create our folder exactly like:
我们需要做的第一件事是正确配置目录结构,以便Next.js识别动态路径。 为了设置动态路由,我们需要创建文件夹,如下所示:
- pages
-- character
--- [id]
-- index.js
Yes, that means you’re literally creating a folder with the name of [id]
, that’s not meant to be replaced. Next.js recognizes that pattern and will let us use that to create a dynamic route.
是的,这意味着您实际上是在创建一个名称为[id]
的文件夹,而不是要替换该文件夹。 Next.js可以识别该模式,并让我们使用它来创建动态路由。
To make creating the page easier, we’re going to simply duplicate our homepage by copying our pages/index.js
file into our next directly.
为了使创建页面更容易,我们将直接复制页面,方法是将pages/index.js
文件直接复制到下一个pages/index.js
。
So we should now have a new page at pages/character/[id]/index.js
.
因此,我们现在应该在pages/character/[id]/index.js
有一个新页面。
Next, let’s remove a bunch of stuff so we can get to a good starting point:
接下来,让我们删除一堆东西,以便我们有一个好的起点:
Remove everything above the
return
statement in our page’s function component删除页面功能组件中
return
语句上方的所有内容- Rename the function component Character重命名功能组件字符
Remove the
useState
anduseEffect
imports删除
useState
和useEffect
导入- Remove the description, search form, grid, and load more button删除描述,搜索表单,网格并加载更多按钮
- Optional: remove the footer可选:删除页脚
Once you’re done, the top of our page’s function component should look like:
完成后,页面功能组件的顶部应如下所示:
export default function Character({ data }) {return (<div className="container"><Head><title>Create Next App</title><link rel="icon" href="/favicon.ico" /></Head><main><h1 className="title">Wubba Lubba Dub Dub!</h1></main>
While there is some CSS we don’t need, we’re going to leave it all there for this demo. Feel free to clean some of that out later.
尽管有一些我们不需要CSS,但在本演示中将保留所有这些内容。 以后随时清理其中的一些。
If you navigate manually to /character/1, you should now see a simple page with just a title:
如果您手动导航到/ char / 1,现在您应该会看到一个只有标题的简单页面:
Next, let’s update the data we’re fetching. We can reuse most of the code in our getServerSideProps
function.
接下来,让我们更新正在获取的数据。 我们可以在getServerSideProps
函数中重用大多数代码。
We’re going to add a new argument to that getServerSideProps
function:
我们将向该getServerSideProps
函数添加一个新参数:
export async function getServerSideProps({ query }) {
When our page is rendered, Next.js injects data into our page and the getServerSideProps
function about the environment. Here, we’re destructuring that data to grab the query
object which will include any dynamic routing attributes, such as the [id]
we’re setting in the route.
呈现我们的页面时,Next.js将数据注入到我们的页面以及有关环境的getServerSideProps
函数中。 在这里,我们正在解构该数据以获取query
对象,该query
对象将包含任何动态路由属性,例如我们在路由中设置的[id]
。
Next, at the top of the getServerSideProps
function, let’s destructure the ID:
接下来,在getServerSideProps
函数的顶部,让我们getServerSideProps
ID:
const { id } = query;
And finally let’s use that ID to dynamically create an endpoint we’ll use to fetch our character data:
最后,让我们使用该ID动态创建一个端点,以用于获取字符数据:
const res = await fetch(`${defaultEndpoint}${id}`);
Here, we’re using our character endpoint and appending the dynamic ID of our URL to the end of the URL.
在这里,我们使用字符端点,并将URL的动态ID附加到URL的末尾。
To test this out, let’s add a console.log
to the top of the Character
function:
为了测试这一点,让我们在Character
函数的顶部添加console.log
:
export default function Character({ data }) {console.log('data', data);
And if we hit save and reload our page, we should now see the user details about character number 1 logged out, which is Rick Sanchez!
而且,如果单击保存并重新加载页面,现在我们应该已经注销了有关字符编号1的用户详细信息,这就是Rick Sanchez!
So we have the data, let’s add it to our page.
这样我们就有了数据,让我们将其添加到页面中。
At the top of the character function, let’s add this destructure statement:
在字符函数的顶部,让我们添加以下分解语句:
const { name, image, gender, location, origin, species, status } = data;
This gives us a bunch of attributes we’re getting right from that data object we saw logged out.
这为我们提供了一些属性,我们可以从看到的已注销数据对象中获取正确的属性。
To use that, we can start by updating the title to that name:
要使用它,我们可以先将标题更新为该名称:
<title>{ name }</title>
Also the <h1>
:
也是<h1>
:
<h1 className="title">{ name }</h1>
At this point, we should now dynamically see Rick’s name.
在这一点上,我们现在应该动态地看到里克的名字。
Next, let’s add this block below our <h1>
to include more of our character details:
接下来,让我们在<h1>
下面添加此块,以包含更多字符详细信息:
<div className="profile"><div className="profile-image"><img src={image} alt={name} /></div><div className="profile-details"><h2>Character Details</h2><ul><li><strong>Name:</strong> { name }</li><li><strong>Status:</strong> { status }</li><li><strong>Gender:</strong> { gender }</li><li><strong>Species:</strong> { species }</li><li><strong>Location:</strong> { location?.name }</li><li><strong>Originally From:</strong> { origin?.name }</li></ul></div>
</div>
Here we’re using our characters image
to display a picture of our character and other various metadata to add Character Details.
在这里,我们使用角色image
来显示角色的图片以及其他各种元数据以添加角色详细信息。
We can follow that up by adding this snippet of CSS to our styles:
我们可以通过将以下CSS代码片段添加到样式中来进行后续操作:
.profile {display: flex;margin-top: 2em;
}@media (max-width: 600px) {.profile {flex-direction: column;}
}.profile-image {margin-right: 2em;
}@media (max-width: 600px) {.profile-image {max-width: 100%;margin: 0 auto;}
}
And now we have our character bio!
现在我们有了自己的角色简介!
So a quick recap, we have our new dynamic page. We can go to /character/1
or any ID to see a specific character. Let’s now update our homepage to link to these pages.
快速回顾一下,我们有了新的动态页面。 我们可以转到/character/1
或任何ID来查看特定字符。 现在,让我们更新主页以链接到这些页面。
Back on pages/index.js
, our homepage, let’s first import the Link
component from Next.js:
回到我们的主页pages/index.js
/index.js,让我们首先从Next.js导入Link
组件:
import Link from 'next/link'
Next, inside of our grid where we map through our list of results, let’s use our <Link>
component and update our code:
接下来,在我们通过结果列表进行映射的网格内部,让我们使用<Link>
组件并更新代码:
<li key={id} className="card"><Link href="/character/[id]" as={`/character/${id}`}><a><img src={image} alt={`${name} Thumbnail`} /><h3>{ name }</h3></a></Link>
</li>
Here’s what we’re doing:
这是我们正在做的:
First we’re wrapping our
<a>
element with a<Link>
component首先,我们用
<Link>
组件包装<a>
元素We add a
href
and theas
properties to describe to Next.js what page we want to link to. We need to use theas
property as it’s a dynamic link我们添加
href
和as
属性,以向Next.js描述我们要链接到的页面。 我们需要使用as
属性,因为它是动态链接We remove the
href
from our<a>
element as it’s now being applied to the<Link>
element我们将
href
从<a>
元素中删除,因为它已被应用于<Link>
元素
If we save and reload our homepage, we’ll notice that nothing changed, but when we click any of our characters, we now go to their bio page!
如果我们保存并重新加载我们的主页,我们会注意到没有任何变化,但是当我们单击任何字符时,我们现在转到其履历页面!
Finally, let’s also add a button to our character bio page that links back to our homepage to make it easier to navigate.
最后,让我们在角色简介页面上添加一个按钮,该按钮可以链接回到我们的主页,从而更易于浏览。
First, let’s import the Link
component:
首先,让我们导入Link
组件:
import Link from 'next/link';
At the bottom of our <main>
tag below our .profile
div, let’s add this code:
在.profile
div下面的<main>
标记的底部,让我们添加以下代码:
<p className="back"><Link href="/"><a>Back to All Characters</a></Link>
</p>
And we can add the following basic styles to simply make it look like a link:
我们可以添加以下基本样式以使其看起来像一个链接:
.back a {color: blue;text-decoration: underline;
}
And if we reload the page, we now have link that we can click to go back to the main page with all of our characters!
而且,如果我们重新加载页面,则现在具有链接,可以单击该链接以返回所有字符的主页!
Follow along with the commit!
跟随提交!
奖励步骤:将Rick and Morty Wiki部署到Vercel! (Bonus Step: Deploy your Rick and Morty wiki to Vercel!)
Because we’re using Next.js, Vercel makes it super simple to deploy our app.
由于我们使用的是Next.js,因此Vercel使部署我们的应用程序变得非常简单。
To do this, we need to install the Vercel CLI. We can do that by installing it as an npm module globally:
为此,我们需要安装Vercel CLI 。 我们可以通过将其作为npm模块全局安装来实现:
yarn global add vercel
# or
npm i -g vercel
Now, you can run the vercel
command in your terminal.
现在,您可以在终端中运行vercel
命令。
The first time you run this, you’ll be prompted to log in. You’ll want to use your Vercel account to do this. If you don’t have one, you’ll want to sign up for a free account.
首次运行此程序时,系统将提示您登录。您将要使用Vercel帐户执行此操作。 如果您还没有,则需要注册一个免费帐户 。
With the Vercel CLI installed, we can simply run vercel
in our project directory, fill out a few questions, and it will automatically deploy!
安装了Vercel CLI后,我们只需在项目目录中运行vercel
,填写一些问题,它将自动部署!
You can use pretty much all of the defaults, though you will probably need to use a different project name than I’m using.
您几乎可以使用所有默认值,尽管您可能需要使用与我使用的项目名称不同的名称。
But once finished, we now have successfully deployed our new app to Vercel!
但是,一旦完成,我们现在就可以成功地将新应用程序部署到Vercel!
我们还能做什么? (What else can we do?)
更多动态页面 (More dynamic pages)
Every time you make a request to a character, the API returns other endpoints that you can use such as locations and episodes. We can utilize those endpoints and create new dynamic pages, just like our dynamic character profile pages, to allow people to see more information about a specific location or episode.
每次您请求角色时,API都会返回您可以使用的其他端点,例如位置和情节。 就像我们的动态角色资料页面一样,我们可以利用这些端点并创建新的动态页面,以允许人们查看有关特定位置或情节的更多信息。
添加一些样式 (Add some styles)
We stuck with some of the basic styles that Next.js included and added some basic ones just for demonstration purposes. But now that you’re finished, you can have some fun and make it your own!
我们坚持使用Next.js包含的一些基本样式,并添加了一些仅用于演示目的的基本样式。 但是,既然您已经完成工作,就可以享受一些乐趣,然后自己创造一个!
添加字符过滤器 (Add character filters)
In addition to filtering by name, the API also supports filtering by status. By adding a status
parameter to the endpoint URL, just like our name
parameter, you can add a new filter to make it easier to find characters that are still alive or not.
除了按名称过滤外, API还支持按状态过滤 。 像我们的name
参数一样,通过将status
参数添加到端点URL,您可以添加一个新的过滤器,以使其更容易找到仍然存在的字符。
如何使用Next.js创建动态的Rick and Morty Wiki Web App相关推荐
- 【ASP.NET Web API教程】2.3.5 用Knockout.js创建动态UI
[ASP.NET Web API教程]2.3.5 用Knockout.js创建动态UI 原文:[ASP.NET Web API教程]2.3.5 用Knockout.js创建动态UI 注:本文是[ASP ...
- matlab 创建批量文件夹_Matlab开发Web App服务器(一)
从2018a开始Matlab提供了Web Apps功能,它能够将电脑设为服务器,把App程序发布到局域网,可以通过浏览器访问.使用步骤为 使用App Designer创建交互式的应用程序: 使用Web ...
- 动态js创建数组对象
动态js创建数组对象 var items = []; for (var i = 0; i < 10; i++) { items.push({ id: i, level: i + '级' }) }
- python 全栈开发,Day116(可迭代对象,type创建动态类,偏函数,面向对象的封装,获取外键数据,组合搜索,领域驱动设计(DDD))...
昨日内容回顾 1. 三个类 ChangeList,封装列表页面需要的所有数据.StarkConfig,生成URL和视图对应关系 + 默认配置 AdminSite,用于保存 数据库类 和 处理该类的对象 ...
- 动态添加组件_使用vue.js的动态组件模板
最近刚做完建站工具,准备总结里面使用到的一些技巧,同时会做一版简化的放在 github上. 先来一篇翻译的文章,和我在项目中使用的动态组件思路一样,不过缺少了演化的过程,直接给出了最终的解决方案.这篇 ...
- 使用Kakapo.js进行动态模拟
by zzarcon 由zzarcon 使用Kakapo.js进行动态模拟 (Dynamic mocking with Kakapo.js) 3 months after the first comm ...
- 在Angular 8中使用自定义MultiSelect下拉菜单创建动态行
目录 介绍 如何工作? 先决条件 使用代码 第1步 第2步 第3步 第4步 第5步 第6步 第7步 第8步 第9步 第10步 第11步 结论 介绍 在本文中,我们将学习如何使用Angular 8创建动 ...
- 【微信小程序】创建动态组件和引用的方法
实战内容:创建微信小程序动态组件并在其他页面中引用该组件 欢迎关注收藏订阅专栏!!! 文章目录 一.今日实战目标 二.实战步骤 1.创建动态组件 2. 局部引用组件 3. 全局引用组件 三.注意事项 ...
- 通过JS代码动态生成HTML表格(Table),Input框,Button按钮.并且通过Input框的值进行查询动态生成数据填写在指定的表格里
本人公众号上线啦!!! 公众号与博客名一样:没有腹肌的程序猿 公众号文章类型:工作上所遇到的需求实现方案分享. 此外也会提供一些数据集供大家使用.(这个还在规划中,毕竟打工人时间挺紧的,哈哈哈哈) 到 ...
最新文章
- oracle数据库如何写翻页_ORACLE数据库分页查询/翻页 最佳实践
- 中国一次性塑料餐具市场运营动态及供需态势分析报告2022年版
- 问题生成的多样性会在多大程度上帮助下游QA任务?
- hazelcast_Hazelcast的MapLoader陷阱
- KNN实现CIFAR-10数据集识别
- win7电脑内存信息的查看方法
- 剑指offer - 二维数组中的查找
- linux7编译mysql5.7安装,CentOS 7.4 使用源码包编译安装MySQL 5.7.20
- 2019年7月9日星期二(C语言)
- [转]Mac OS X 下部分Android手机无法连接adb问题之解决方案
- 比较笨的中文预处理 python
- mysql事务控制(xa分布式事务)和锁定语句_MySQL的SQL语句 -事务性语句和锁定语句(7)- XA 事务...
- matlab 差影法,MATLAB人体姿态行为识别[差影法,多姿势]
- OSGEARTH三维地形开源项目
- 【转】资深眼镜人告诉你一些所不为人知的眼镜知识和内幕
- 【知识兔】自学Excel之11:模板使用和打印设置
- Android-使用HttpURLConnection实现多线程下载
- 白帽子讲Web安全(一)浏览器安全
- 华为rh2288v2服务器系统,灵动高效!华为RH2288 V2服务器评测
- 飞塔防火墙密码忘记重置方法
热门文章
- 【ASP.NET Web API教程】2.3.5 用Knockout.js创建动态UI