基本介绍
Remix is a full stack web framework that lets you focus on the user interface and work back through web standards to deliver a fast, slick, and resilient user experience. People are gonna love using your stuff.
- 是一个现代化的前端框架,由Echonest团队构建,旨在为开发者提供一种更简单、更直观的方式来构建全功能的Web应用程序。它采用了React库,并结合了服务器端渲染(SSR)和客户端交互的能力,让开发者能够高效地创建高性能且用户体验优良的应用。
特点
- 简洁API - Remix的API设计得非常简洁,降低了学习曲线,让开发者可以更快地上手。
- 开箱即用的工具链 - 提供了一整套预配置的工具,如webpack、ESLint等,开发者无需花费时间配置即可开始编码。
- 易于测试 - 由于Remix的模块化结构,每个功能都独立封装,因此单元测试变得更容易。
开始
- 输入命令行
npx create-remix@latest

- 运行项目
npm run dev
目录
├─ .eslintrc.cjs├─ .gitignore├─ app│ ├─ entry.client.tsx│ ├─ entry.server.tsx│ ├─ root.tsx│ ├─ routes│ │ └─ _index.tsx│ └─ tailwind.css├─ package-lock.json├─ package.json├─ postcss.config.js├─ public│ └─ favicon.ico├─ README.md├─ tailwind.config.ts├─ tsconfig.json└─ vite.config.ts
/app一般存放主要的文件/app/routes文件夹下的是存放路由entry.client.tsx此文件是浏览器的入口点entry.server.tsx此模块的导出是一个函数,可让您创建响应,包括 HTTP 状态、标头和 HTML,让您完全控制生成标记并将其发送到客户端的方式root.tsx生成HTML元素文件
路由文件命名
- 在
routes文件夹下创建的文件将会自动创建页面路由,相关的路由文件名命名规则:https://remix.run/docs/en/main/file-conventions/routes
| URL 网址 | Matched Route 匹配路线 | 说明 |
|---|---|---|
| / | app/routes/_index.tsx | |
| /about | app/routes/about.tsx | |
| /concerts/trending | app/routes/trending.tsx | |
| /concerts/salt-lake-city | app/routes/$city.tsx | salt-lake-city是动态参数,可以使用params来接收,使用 $ 前缀创建它们 |
| /concerts/san-diego | app/routes/$city.tsx | san-diego是动态参数,可以使用params来接收,使用 $ 前缀创建它们 |
| /concerts | app/routes/concerts._index.tsx | 嵌套路由,使用 |
| /concerts/mine | app/routes/concerts_.mine.tsx | 没有布局嵌套的URL,选择在父段上使用尾随下划线来退出嵌套 |
| /login | app/routes/_auth.login.tsx | 与一组路由共享布局,而不向 URL 添加任何路径段 |
| /en/categories | app/routes/($lang).categories.tsx | 将路线段括在括号中将使该段成为可选的 |
| /beef/and/cheese | app/routes/$.tsx | 可以使用 "*" 键访问 splat 路由的 params 上匹配路径的值 |
| /files/talks/remix-conf_old.pdf | app/routes/files.$.tsx | |
| /sitemap.xml | app/routes/sitemap[.]xml.tsx | 特殊字符 |
核心数据流

Loader
此函数运行在服务器上,初始化服务器时,他向HTML文档提供数据
- 其实可以理解为RESTFUL接口中的GET请求
import { json } from "@remix-run/node";export const loader = async ({request,context,params}) => {return json({ ok: true });};
request
request 是一个 Fetch API Request 对象,代表 HTTP 请求。它包含请求方法、请求头、请求体等信息。你可以使用这个对象来获取请求的详细信息或传递给其他 API 调用。
一般会使用的方法
- new URL:创建一个 URL 对象
URL对象具有以下常用属性:href: 完整的 URL 字符串。protocol: URL 的协议部分(例如,http:或https:)。hostname: URL 的主机名(例如,example.com)。port: URL 的端口号。pathname: URL 的路径部分(例如,/path)。search: 查询字符串(包括开头的?)。searchParams: 一个URLSearchParams对象,表示查询参数。hash: URL 的哈希部分(包括开头的#)。
const url = new URL('https://example.com:8000/path?name=value#hash');console.log(url.href);// 'https://example.com:8000/path?name=value#hash'console.log(url.protocol);// 'https://'console.log(url.hostname);// 'example.com'console.log(url.port);// '8000'console.log(url.pathname);// '/path'console.log(url.search);// '?name=value'console.log(url.hash);// '#hash'console.log(url.searchParams);// URLSearchParams { 'name' => 'value' }const url = new URL(request.url);const searchParams = new URLSearchParams(url.search);const discount = searchParams.get('discount');
context
context是一个上下文对象,可以在 Remix 应用程序中传递额外的数据或功能。这个参数通常由开发者在创建 Remix 应用时自定义,例如数据库连接、第三方 API 客户端等。
params
params 包含 URL 参数。这些参数通常是由路由定义中的动态片段匹配的。例如,如果路由是 /posts/:postId,那么 params 对象将包含 postId 的值。
Components
路由模块的默认导出定义了路由匹配时将呈现的组件。
- 可以接收Loader上的数据
export default function Users() {const data = useLoaderData<typeof loader>();return (<ul>{data.map((user) => (<li key={user.id}>{user.name}</li>))}</ul>);}
Action
路由 action 是一个仅用于处理数据突变和其他操作的服务器函数。如果对您的路线发出非 GET 请求(DELETE、PATCH、POST 或 PUT )然后在 loader 之前调用该操作。
- 其实可以理解为RESTFUL接口中的GET请求
<font style="color:rgb(67, 67, 67);">action</font>与<font style="color:rgb(67, 67, 67);">loader</font>具有相同的 API,唯一的区别在于调用它们的时间。这使您能够将有关数据集的所有内容共同定位在单个路由模块中:数据读取、呈现数据的组件以及数据写入:
import type { ActionFunctionArgs } from "@remix-run/node"; // or cloudflare/denoimport { json, redirect } from "@remix-run/node"; // or cloudflare/denoimport { Form } from "@remix-run/react";import { TodoList } from "~/components/TodoList";import { fakeCreateTodo, fakeGetTodos } from "~/utils/db";export async function action({request,}: ActionFunctionArgs) {const body = await request.formData();const todo = await fakeCreateTodo({title: body.get("title"),});return redirect(`/todos/${todo.id}`);}export async function loader() {return json(await fakeGetTodos());}export default function Todos() {const data = useLoaderData<typeof loader>();return (<div><TodoList todos={data} /><Form method="post"><input type="text" name="title" /><button type="submit">Create Todo</button></Form></div>);}
