混音:一些不同的东西

2025-06-07

混音:一些不同的东西

大约三年前,我从 Web 开发爱好转向了 Web 开发工作。我之所以能找到这份工作的信心,部分原因在于我在这里公开学习开发的经验,所以,本着同样的理念,我决定尝试学习Remix

在开始之前,我应该声明一下,我是一名前端开发者,后端经验很少。我之前用过 NodeJS,也涉猎过 PHP 和 Perl。我也知道 NextJS 很流行,甚至可能是更好的入门选择,但我决定先看看 Remix 能提供什么。以后我可能会考虑 NextJS,看看情况如何。

至少一开始我会先按照Remix 网站上的博客教程来做。如果我觉得有点道理,我可能会停止学习,看看最终会怎样。好了,废话不多说,我们开始吧。

设置

首先,让我们创建一个工作空间。我创建了一个名为 的新文件夹remix-server(虽然名称并不重要),然后打开了 VSCode。在终端中,我输入了npx create-remix@latest并按照说明进行操作。

Need to install the following packages:
  create-remix@latest
Ok to proceed? (y)

R E M I X

💿 Welcome to Remix! Let’s get you set up with a new project.

? Where would you like to create your app? .
? Where do you want to deploy? Choose Remix if you’re unsure, it’s easy to change deployment targets. Remix App Server
? TypeScript or JavaScript? TypeScript       
? Do you want me to run `npm install`? Yes

> postinstall
> remix setup node

Successfully setup Remix for node.
Enter fullscreen mode Exit fullscreen mode

当它询问我想要在哪里创建应用程序时,我刚才使用了.这个名称,如果我想创建一个新目录,我可以像这里一样写入目录名称.\my-dir

您可能还注意到我使用的是 Typescript 而不是 JavaScript,这是因为我正在学习 Typescript,但如果您想使用 JS,那没问题,我确信我们编写的大部分内容都是可转移的。

一旦 NPM 完成其工作,我就可以运行npm run dev并查看服务器。

Remix 默认屏幕

制定路线

如果我们查看已创建的文件,您会注意到有一个名为 的文件夹app,其中还有一个名为 的文件夹,routes该文件夹内有一个名为 的文件index.tsx,该tsx文件是 TypeScript React 文件,您可能会看到jsx它与 JS 等效。我查看了索引文件,发现它是一个看起来很正常的 React 文件,其中包含我们刚刚制作的演示页面的内容。

在教程中继续阅读,我们发现它要求我们修改索引文件并创建新的路线,所以让我们这样做,但也要稍微偏离脚本,以确保我们知道发生了什么。

我计划修改索引文件,使其包含一个,Link就像教程中提到的那样。之后,我会新建一个名为 test 的目录,并在其中放入一个名为 index 的文件和另一个名为 inner 的文件。这样,我就能访问localhost:3000localhost:3000/testlocalhost:3000/test/inner查看我的三个文件了。

/* base level index */
import { Link } from "remix";

export default function Index() {
  return (
    <>
      <h1>This is a test</h1>
      <Link to="/test">Test page</Link>
    </>
  );
}

/* Index file inside '/test' */
import { Link } from "remix";

export default function TestIndex() {
  return (
    <>
      <h1>This is a test</h1>
      <Link to="/test/inner">Test inner</Link>
    </>
  );
}

/* File called inner inside '/test' */
export default function Inner() {
  return (
    <>
      <h1>You found me!!</h1>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

你知道它的工作原理吗?路由文件夹内的任何目录似乎都会变成路由,如果路由中包含索引文件,则直接访问该路由即可访问该文件,其他文件也可以通过在 URL 中路由后输入其名称来访问。我相信以后还会遇到比这更复杂的情况,但目前看来,理解这些已经足够了。

让我们继续本教程。

获取数据

这部分我觉得有点乱,它一开始就让你把所有代码都放在一个文件中,然后告诉你这不是最佳实践,并让你重构它。另外,在 TypeScript 版本中,当接口工作正常时,它会让你使用 Type。我会告诉你我做了哪些不同的事情,虽然最终不会有太大的不同,但我觉得这样可以减少困惑。

useLoaderData 钩子

首先,我们需要使用一个名为useLoaderData“导入”的钩子remix,就像我们之前在 link 中做的那样。这还需要我们从正在使用的文件中导出一个useLoaderData名为 loader 的函数。最佳实践是使用这个函数async,因为它允许我们等待数据加载。loader 函数应该以我们想要在 React 文件中使用的格式返回数据。

import { useLoaderData } from "remix";

export const loader = async () => {
  return 'hello world';
};

export default function Posts() {
  const loadedData = useLoaderData();

  return (
    <>
      <h1>Posts!</h1>
      {loadedData}
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

上面的代码片段将打印“hello world”,就像函数返回的loadedData那样loader

现在,如果我们想从中获取更复杂的数据,loader最好创建一个包含该函数的新文件,然后将该函数导入到我们的 React 文件中,并在loader函数内部使用它。由于我们不希望这个新文件包含路由,因此让我们回到上app一级,并创建一个名为“loaders”的新文件夹,在这里我们将创建一个名为的文件posts.ts

export interface Post {
  slug: string;
  title: string;
}

export const getPosts = (): Post[] => {
  return [
    {
      slug: "my-first-post",
      title: "My First Post",
    },
    {
      slug: "90s-mixtape",
      title: "A Mixtape I Made Just For You",
    },
  ];
};
Enter fullscreen mode Exit fullscreen mode

此文件包含一个描述返回数据的接口getPosts。我们还包含一个名为 的函数getPosts,它只返回我们想要获取的“数据”。将来,它可能会包含一些数据库调用或其他内容,但现在我们先保持简单。接口和函数都已导出,以便我们可以在帖子索引文件中使用它们。

import { Link, useLoaderData } from "remix";

import { getPosts, Post } from "~/loaders/post";

export const loader = async () => {
  return getPosts();
};

export default function Posts() {
  const posts = useLoaderData<Post[]>();

  return (
    <>
      <h1>Posts!</h1>
      {posts.map((post) => (
        <li key={post.slug}>
          <Link to={post.slug}>{post.title}</Link>
        </li>
      ))}
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

如你所见,我们导入了接口和函数。接口允许我们修改useLoaderData函数,这样一来,IDE 就能自动补全postsconst is 和 s 数组,Post就像接口描述的那样。

动态路由

要添加动态路由,请在 routes 目录中创建一个新文件。该文件必须以 开头,$但名称的其余部分可以随意命名。在 remix 给出的示例中,他们使用了 ,slug因此我们也照做。

当你这样做的时候,一些神奇的事情发生了。之前的加载函数可以看到你输入的 URL 并对其进行处理,但让我们退一步来看看这里到底发生了什么。

事实证明,加载器函数总是会传递一个我们可以使用的对象。该对象包含一个request对象,一个context(对我来说是未定义的),以及一个params对象。请求是服务器接收的完整请求,包括完整的 URL、方法(在本例中为 GET),甚至还有一个以后可能会用到的查询。现在我们对加载器函数的功能有了简单的了解,让我们继续。

我们关心的 URL 部分存储在加载器参数的 params 部分中,在我们的例子中,它被称为文件名称减去$, 。slug

export const loader: LoaderFunction = async ({params}) => {
  return params.slug;
};
Enter fullscreen mode Exit fullscreen mode

LoaderFunction是我们从 remix 导入的一种类型,以使 typescript 能够正常工作。

加载数据

我们可以使用像 fs 这样的常规 NodeJS 工具从文件系统加载文件。本教程指导我们在 app 目录下创建一些可以加载的 Markdown 文件。

使用fs我们可以获取所有文件名的列表,还可以使用 加载位于 md 中的帖子标题parseFrontMatter。这些数据可以结构化,以替换旧的静态帖子数组。

现在我们需要一个新的函数,它可以从动态路由中获取 slug,并打开文件并将其显示md为 HTML。我们再次使用fs来加载文件,然后使用marked将其转换md为 HTML。我们调用这个函数getPost,并将其导入到我们的$slug文件中,就完成了。

回顾

回顾一下,

  • 使用 npm 启动一个新项目
  • 制定了一些自定义路线
  • 加载一些数据来构建动态内容列表
  • 读取md文件并将其转换为 html
  • 在动态路由中显示该 html

感觉内容很多,但又不算太多。教程才进行到一半,但这篇文章已经很长了,所以感觉现在是时候停下来了。

感谢您的阅读,这真的意义重大。请随时留言,哪怕只是告诉我哪里做错了,或者哪里可以改进。

如果您想在 Dev 之外与我联系,这里有我的推特领英,来打个招呼吧😊。

文章来源:https://dev.to/link2twenty/remix-something- Different-1i06
PREV
2024 年构建响应式设计的最佳实践
NEXT
React:媒体查询的自定义钩子📱💻