Skip to content

数据获取

Fresh 中的数据获取发生在服务器端。处理器加载数据并通过 page() 辅助函数将其传递给页面组件。这样可以将 API 密钥、数据库连接和敏感逻辑排除在浏览器之外。

处理器与页面组件

处理器获取数据并使用 page() 返回。页面组件通过 props.data 接收数据:

tsx
import { HttpError, page } from "fresh";
import { define } from "@/utils.ts";

interface Data {
  project: { name: string; stars: number };
}

export const handler = define.handlers({
  async GET(ctx) {
    const project = await db.projects.findOne(ctx.params.id);
    if (!project) {
      throw new HttpError(404);
    }
    return page({ project });
  },
});

export default define.page<typeof handler>(({ data }) => {
  return (
    <div>
      <h1>{data.project.name}</h1>
      <p>{data.project.stars} stars</p>
    </div>
  );
});

define.page<typeof handler> 泛型将处理器的返回类型关联到组件的 props,让你在 data 上获得完整的自动补全。

设置响应头和状态码

page() 传递选项来自定义 HTTP 响应:

ts
return page(data, {
  status: 201,
  headers: { "Cache-Control": "public, max-age=3600" },
});

异步页面组件

对于更简单的场景,你可以直接在异步组件中获取数据,而无需单独的处理器:

tsx
import { HttpError } from "fresh";
import { define } from "@/utils.ts";

export default define.page(async (ctx) => {
  const project = await db.projects.findOne(ctx.params.id);
  if (!project) {
    throw new HttpError(404);
  }

  return (
    <div>
      <h1>{project.name}</h1>
      <p>{project.stars} stars</p>
    </div>
  );
});

当你不需要处理器和组件之间的类型安全数据桥接时,这种方式很方便。

从中间件传递状态

中间件 可以在 ctx.state 上设置值,这些值可供所有下游处理器和组件使用:

ts
import { define } from "@/utils.ts";

export default define.middleware(async (ctx) => {
  const session = await getSession(ctx.req);
  ctx.state.user = session?.user ?? null;
  return ctx.next();
});
tsx
import { page } from "fresh";
import { define } from "@/utils.ts";

export const handler = define.handlers({
  GET(ctx) {
    if (!ctx.state.user) {
      return ctx.redirect("/login");
    }
    return page();
  },
});

export default define.page((ctx) => {
  return <h1>Welcome, {ctx.state.user.name}</h1>;
});

页面 props 中可用的内容

页面组件接收以下属性:

属性类型描述
dataData处理器通过 page() 返回的数据
urlURL请求 URL
paramsRecord<string, string>路由参数(例如 :id
reqRequest原始 HTTP 请求
stateState中间件设置的共享状态
configResolvedFreshConfig已解析的 Fresh 配置
routestring | null匹配的路由模式
infoDeno.ServeHandlerInfo服务器连接信息
errorunknown | null捕获的错误(在错误页面上)
isPartialboolean是否为部分请求
ComponentFunctionComponent子组件(在布局中)