使用您最喜欢的AI助手总结文档,并引用此页面和AI提供商
此页面的内容已使用 AI 翻译。
查看英文原文的最新版本如果您有改善此文档的想法,请随时通过在GitHub上提交拉取请求来贡献。
文档的 GitHub 链接复制文档 Markdown 到剪贴板
import Since from '/components/Since.astro';
import ReadMore from '/components/ReadMore.astro';
会话(session)是用于存储 按需渲染页面 在请求间的数据。
不同于 cookies,因为会话存储在服务端,所以对于存储更大体积的数据或是安全问题,你都无需担忧。会话存储适用于用户信息、购物车内容以及表单状态,且无需客户端 JavaScript:
复制代码到剪贴板
---export const prerender = false; // Not needed with 'server' outputconst cart = await Astro.session?.get('cart');---<a href="/checkout">🛒 {cart?.length ?? 0} items</a>
配置会话
会话需要一个存储驱动来将会话数据保存起来。Node、Cloudflare 和 Netlify 适配器都会为你自动配置默认的驱动,但是其他的适配器目前需要你 手动指定驱动
复制代码到剪贴板
{ adapter: vercel(), session: { driver: "redis", }, }
使用会话数据
session 对象 允许你与存储的用户状态(例如,向购物车中添加商品)和会话 ID(例如,当退出登录时,删除会话 ID cookie)进行交互。该对象可以在你的 Astro 组件中作为 Astro.session 被访问到,而在页面的 API 端点、中间件和 action 中,则作为 context.session 对象被访问。
会话将在首次使用时自动生成,会话也可以随时使用 Astro.session.regenerate() 重新生成,或使用 Astro.session.destroy() 销毁。
在大多数情况下,只需使用 Astro.session.get() 和 Astro.session.set() 即可。
Astro 组件和页面
在 .astro 组件和页面中,你可以通过全局的 Astro 对象来访问会话对象。例如,显示购物车中的商品数量:
复制代码到剪贴板
---export const prerender = false; // 无需使用 'server' 输出const cart = await Astro.session?.get('cart');---<a href="/checkout">🛒 {cart?.length ?? 0} items</a>
API 端点
在 API 端点中,会话对象在 context 对象中可用。例如,向购物车中添加一个商品:
复制代码到剪贴板
export async function POST(context: APIContext) { const cart = await context.session?.get('cart') || []; const data = await context.request.json<{ item: string }>(); if(!data?.item) { return new Response('Item is required', { status: 400 }); } cart.push(data.item); await context.session?.set('cart', cart); return Response.json(cart);}
Actions
在 action 中,会话对象在 context 对象中可用。例如,向购物车中添加一个商品:
复制代码到剪贴板
import { defineAction } from 'astro:actions';import { z } from 'astro:schema';export const server = { addToCart: defineAction({ input: z.object({ productId: z.string() }), handler: async (input, context) => { const cart = await context.session?.get('cart'); cart.push(input.productId); await context.session?.set('cart', cart); return cart; }, }),};
中间件
:::note 边缘中间件(edge middleware)不支持会话功能。 :::
在中间件中,会话对象在 context 对象中可用。例如,在会话中设置最后访问的时间:
复制代码到剪贴板
import { defineMiddleware } from 'astro:middleware';export const onRequest = defineMiddleware(async (context, next) => { context.session?.set('lastVisit', new Date()); return next();});
会话数据类型
默认情况下,会话数据的类型是未被定义的,你可以将任意数据存储在任何 key 中。使用 devalue 对值进行序列化和反序列化,该库与 content layer 和 action 所使用的库相同。这意味着支持的类型是相同的,包括字符串、数字、Date、Map、Set、URL、数组和简单对象。
你可以通过创建 src/env.d.ts 文件并为 App.SessionData 添加类型,来选择性地为你的会话数据定义 TypeScript 类型:
复制代码到剪贴板
declare namespace App { interface SessionData { user: { id: string; name: string; }; cart: string[]; }}
这将使你可以在编辑器中访问会话数据时,使用类型检查和自动补全:
复制代码到剪贴板
---const cart = await Astro.session?.get('cart');// const cart: string[] | undefinedconst something = await Astro.session?.get('something');// const something: anyAstro.session?.set('user', { id: 1, name: 'Houston' });// Error: Argument of type '{ id: number; name: string }' is not assignable to parameter of type '{ id: string; name: string; }'.---
:::caution 这仅用于类型检查,不会影响会话的运行时行为。如果你在用户使用会话来存储数据时更改了类型,请格外小心,因为这可能会导致运行时错误。 :::