文档共享合约
操作和导航
Nexy 中的交互是通过 Actions 和 Navigation 的统一系统进行处理,确保前端和后端保持同步,无需手动 API 粘合代码。
行动契约
Action 是一个处理突变(例如更新数据库)的服务器端函数。
- 类型化输入:操作在 Python 中定义,带有类型提示。 Nexy 生成匹配的 TypeScript 客户端,因此您可以在 IDE 中获得自动完成和验证。
- 原子执行:一个操作是单个
POST请求。 - 结果处理:操作返回客户端可用于更新 UI 的类型化结果。
from pydantic import BaseModelfrom nexy.decorators import Action class Todo(BaseModel): title: str done: bool = False @Actionasync def add_todo(title: str) -> Todo: return Todo(title=title)该页面使用声明的输入 Python 调用它,并返回一个类型化的 Todo:
import { useAction } from "@nexy/client";import { add_todo } from "@nexy/actions"; export default function Todos() { const { run, pending, data } = useAction(add_todo); return ( <button disabled={pending} onClick={() => run({ title: "Write the docs" })}> {data ? `Added ${data.title}` : "Add"} </button> );}该组件是一个视图岛,控制器返回该视图:
import { useAction } from "@nexy/client";import { add_todo } from "@nexy/actions"; export function Todos() { const { run, pending, data } = useAction(add_todo); return ( <button disabled={pending} onClick={() => run({ title: "Write the docs" })}> {data ? `Added ${data.title}` : "Add"} </button> );}from "@/components/Todos.tsx" import Todos<Todos directive="client:load" />客户端导航
Nexy 的导航是“智能的”。 Nexy 不是完全重新加载浏览器,而是交换当前页面的内容,同时保持活动布局的安装。
Link组件:使用特定于框架的Link组件执行客户端转换。- 编程式导航:使用
@nexy/client中的useRouter()并调用push()来更改页面以响应逻辑(例如,成功登录后)。
import { Link } from "@nexy/client"; export function Nav() { return ( <nav> <Link href="/">Home</Link> <Link href="/about" activeClassName="active">About</Link> </nav> );}import { useRouter } from "@nexy/client"; export function Done() { const router = useRouter(); return <button onClick={() => router.push("/dashboard")}>Continue</button>;}协调:行动→导航
最常见的模式是执行操作,然后将用户导航到新页面。
重新验证流程:
- 客户端调用一个操作。
- 该操作在服务器上执行并调用
revalidate("/path")。 - 服务器返回带有
x-nexy-revalidate标头的结果,该标头命名了过时路径。 - 客户端更新页面内容以反映新状态。
from nexy.decorators import Action, revalidate @Actionasync def sign_in(email: str, password: str) -> bool: ok = check_password(email, password) revalidate("/dashboard") return okimport { useAction, useRouter } from "@nexy/client";import { sign_in } from "@nexy/actions"; export default function Login() { const router = useRouter(); const { run } = useAction(sign_in, { onSuccess: (ok) => { if (ok) router.push("/dashboard"); }, }); return <button onClick={() => run({ email: "ada@example.com", password: "..." })}>Sign in</button>;}import { useAction } from "@nexy/client";import { sign_in } from "@nexy/actions"; export function Login() { const { run } = useAction(sign_in, { onSuccess: (ok) => { if (ok) window.location.assign("/dashboard/"); }, }); return <button onClick={() => run({ email: "ada@example.com", password: "..." })}>Sign in</button>;}check_password 代表您自己的支票。有关错误、没有 JavaScript 和安全性的表单,请参阅 操作 。
框架实施
用于调用操作和导航的 API 因框架而异。请参阅您选择的技术的 差异 指南: