
Next.js是一个开源框架,旨在与React一起工作。它被用来构建登陆页面、SEO友好型网站、电子商务商店,以及需要快速、高性能加载时间的各种网络应用。另一方面,TypeScript是一种建立在JavaScript上的编程语言,Next.js支持这种语言。这两者结合起来,为用户和开发者提供了更好的体验。
Next.js和TypeScript主要分别被归类为全栈框架和模板语言及扩展工具,但让我们来看看两者的应用内容和方式,以及它们如何协同工作,包括其应用实例。
目录
什么是Next.js?
➤Next.js用来做什么
➤使用Next.js进行客户端数据
什么是TypeScript?
➤使用TypeScript做什么?
如何在NextJS中安装TypeScript ?
什么是 Next.js?
Next.js 是由 Vercel 创建的一个开源框架。它声称自己是 Web 的软件开发工具包,拥有 "使 Web 更快"(原文如此)所需的所有工具。更快"(原文如此)。在这里了解Next.js与React的功能及其应用。
Next.js有什么用处?
Next.js使搜索引擎能够轻松地优化React应用程序,而无需配置。传统的React应用是在客户端渲染的,浏览器从一个缺乏任何渲染内容的HTML页面的外壳开始。从那里,浏览器获取包含React代码的JavaScript文件,将内容渲染到页面上,并使其具有互动性。然而,客户端渲染有两个主要缺点。
1.内容不能被所有搜索引擎可靠地索引,也不能被社交媒体链接机器人读取;
2. 当用户第一次登陆网页时,可能需要更长的时间才能到达第一个内容丰富的油漆。
Next.js是一个框架,它允许你建立一个React应用程序,但在服务器上提前渲染内容,所以用户或搜索机器人首先看到的是完全渲染的HTML。在收到这个初始页面后,客户端渲染就会接管,它就像一个传统的React应用一样工作。**这是两个世界中最好的:**为机器人提供完全渲染的内容,为用户提供高度互动的内容。
使用Next.js进行客户端数据获取
当我们谈论数据获取时,真正的魔力开始发挥作用,因为Next.js可以从一个项目中执行多种服务器渲染策略。当你的页面不需要SEO索引时,当你不需要预渲染数据时,或者当你的页面内容需要经常更新时,客户端数据获取就很有用。静态生成或预渲染允许你在构建时渲染你的页面。请看下面的例子:
export default function IndexPage() {
const [loading, setLoading] = useState(true);
const [postList, setPostList] = useState([]);
useEffect(() => {
const fetchData = async () => {
const res = await fetch(API_URL);
const posts: IPost[] = await res.json();
setPostList(posts);
setLoading(false);
};
fetchData();
}, []);
//...
在前面的代码片段中可以看到一个使用React的useEffect 钩子进行客户端数据获取的例子。
首先,我们初始化了一些常量来检查获取是否仍在进行,并保存获取过程中产生的数据。然后,我们用两个不同的参数调用useEffect 钩子。
- 回调--包含副作用登录的函数,在变化被推送到DOM后立即运行。在我们的案例中,其逻辑是从一个端点获取数据并将其保存到我们的常量中。
- Dependencies- 一个依赖数组,允许指定回调何时运行。通过传递一个空数组,这意味着我们希望回调只运行一次。
什么是TypeScript?
TypeScript是一种由微软开发和维护的编程语言,它是JavaScript的严格超集。它支持静态和动态类型,并进一步提供了继承特性、类、可见性范围、命名空间、接口、联合体和其他现代特性。TS是为处理大型项目而设计的,因为它更容易重构代码。通过与JavaScript的深入比较,了解更多关于它的功能。
您使用 TypeScript 的目的是什么?
JavaScrip 开发人员考虑使用 TypeScript 的原因有很多。
-
使用ECMAScript的新功能- TypeScript支持ECMAScript标准,并将其转译到您选择的ECMAScript目标,因此您可以使用模块、lambda函数、类、重组等功能。
-
静态类型--JavaScript是一种动态类型,在运行时真正实例化之前,它不知道变量是什么类型;在这里,TypeScript给JavaScript增加了类型支持。
-
类型推理--TypeScript通过使用类型推理,使打字变得更简单,更不明确。即使你不明确地输入类型,它们仍然存在,以拯救你的行为,否则会导致运行时错误。
-
更好的IDE支持--与JavaScript相比,TypeScript的开发经验有很大的改进。有各种各样的IDE对TypeScript有很好的支持,比如Visual Studio和VS Code,IntelliJ和Sublime,或者WebStorm。
-
严格的空值检查- 像 "你不能读取未定义的属性'x'"这样的错误在JavaScript编程中很常见。你可以通过严格检查来避免大多数这类错误,因为人们不能使用TypeScript编译器不知道的变量。
-
互操作性- TypeScript 与 JavaScript 密切相关,因此它有很好的互操作能力,但要在 TypeScript 中与 JavaScript 库一起工作,需要一些额外的工作。
如何在 NextJS 中安装 TypeScript?
以下是在 Next.js 应用程序中安装 TypeScript 的分步指南。
1.创建基础项目--命令。npx create-next-app next-app-example.
用基础模板创建项目。
2.2.在项目的根部添加tsconfig.json ,以激活TypeScript。
3.在表格中构造项目。
src
├── components
| ├── FormTodo.tsx
| └── Todo.tsx
├── pages
├── Todo
├── index.tsx
| ├── index.tsx
| └── _app.tsx
├── styles
| └── index.css
├── tsconfig.json
├── types
| └── index.ts
├── next-env.d.ts
4.在Next.js中创建TypeScript类型
你可以为你的应用程序中的任何东西创建类型,包括道具类型、API响应、函数的参数等等。
我们首先为我们的todos 创建一个类型:
--code
export interface ITodo {
id: number;
description: string;
isDone: boolean;
}
--end code
5.在Next.js中创建组件
现在我们有了我们的ITODO 类型,我们可以创建Todo.tsx 组件:
--code
import React from "react";
import { Button } from "react-bootstrap";
import { ITodo } from "../types";
type Props = {
todo: ITodo;
markTodo: (id: number) => void;
removeTodo: (id: number) => void;
};
const Todo: React.FC<Props> = ({ todo, markTodo, removeTodo }) => {
return (
<div className="todo">
<span style={{ textDecoration: todo.isDone ? "line-through" : "" }}>
{todo.description}
</span>
<div>
{!todo.isDone && (
<Button variant="outline-success" onClick={() => markTodo(todo.id)}>
✓
</Button>
)}
<Button variant="outline-danger" onClick={() => removeTodo(todo.id)}>
✕
</Button>
</div>
</div>
);
};
export default Todo;
--end code
正如你所看到的,我们首先导入了之前创建的类型,同时还创建了另一个名为Props 的类型,它将反映组件所接收到的作为参数的道具。
这个组件负责显示ITodo 对象。这个组件接收ITodo 对象、一个markTodo 函数和一个removeTodo 函数作为道具。注意,这个参数必须与props类型相匹配,以使Typescript满意。
现在让我们来创建我们的FormTodo.tsx 组件,负责在我们的应用程序中添加Todos :
--code
import * as React from "react";
import { Button, Form } from "react-bootstrap";
type Props = {
addTodo: (text: string) => void;
};
const FormTodo: React.FC<Props> = ({ addTodo }) => {
const [value, setValue] = React.useState<string>("");
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!value) return;
addTodo(value);
setValue("");
};
return (
<Form onSubmit={handleSubmit}>
<Form.Group>
<Form.Label>
<b>Add Todo</b>
</Form.Label>
<Form.Control
type="text"
className="input"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Add new todo"
/>
</Form.Group>
<Button variant="primary mb-3" type="submit">
Submit
</Button>
</Form>
);
};
export default FormTodo;
--end code
我们的组件接受addTodo 作为一个参数。它处理提交一个新的Todo 。如果该值不是空的,那么我们就对该todo文本调用addTodo 函数,然后再次将表单的值设置为空。这个组件返回一个接受todos的表单,并有一个提交按钮,通过点击该按钮,我们将todo添加到todo列表中。
6.创建我们的页面,以便使用我们的反应组件。
我们将从导入我们先前创建的组件和类型开始:
-- code
import React from "react";
import { Card } from "react-bootstrap";
import { InferGetStaticPropsType } from "next";
import { ITodo } from "../../types";
import Todo from "../../components/Todo";
import FormTodo from "../../components/FormTodo";
export default function indexPage({
todos,
}: InferGetStaticPropsType<typeof getStaticProps>) {
const [todosList, setTodosList] = React.useState(todos);
const addTodo = (text: string) => {
const newTodo: ITodo = {
id: Math.random(),
description: text,
isDone: false,
};
const newTodos = [...todosList, newTodo];
setTodosList(newTodos);
};
const markTodo = (id: number) => {
const newTodos = todosList.map((todo) => {
if (todo.id === id) {
return {
...todo,
isDone: true,
};
}
return todo;
});
setTodosList(newTodos);
};
const removeTodo = (id: number) => {
const newTodos = todosList.filter((todo) => {
return todo.id !== id;
});
setTodosList(newTodos);
};
return (
<div className="app">
<div className="container">
<h1 className="text-center mb-4">Todo List</h1>
<FormTodo addTodo={addTodo} />
<div>
{todosList.map((todo, index) => (
<Card key={index}>
<Card.Body>
<Todo todo={todo} markTodo={markTodo} removeTodo={removeTodo} />
</Card.Body>
</Card>
))}
</div>
</div>
</div>
);
}
export async function getStaticProps() {
const todos: ITodo[] = [
{
id: 2,
description: "Test next.js app",
isDone: true,
},
{
id: 1,
description: "Build next.js app",
isDone: true,
},
];
return {
props: {
todos,
},
};
}
--end code
在导入组件和类型后,我们导入了InferGetStaticPropsType ,这是由Next.js提供的,允许我们在getStaticProps方法上设置类型。
之后,我们使用useState 钩子初始化了我们的todoList ,将getStaticProps 提供的初始todos作为一个参数。
最后,我们声明了实现我们的逻辑的主要执行部分。
addTodo- 允许在我们的列表中添加一个todoremoveTodo- 允许在我们的列表中删除一个todomarkTodo- 允许在我们的列表中设置一个已完成的todo
最后,我们使用我们的组件返回一个todos的列表。