R

ReflexKR

Reflex 官方文档

用 Reflex 入门 Python 全栈 Web 开发

·

课程概览

1

Reflex 简介与开发环境

2

用组件绘制界面

3

State 与 Var:让数据驱动界面

4

事件与表单:添加客户

5

数据处理与图表

6

总结、调试与下一步

·

附录

用 Reflex 入门 Python 全栈 Web 开发
第3课

时间 1:25–2:10

State 与 Var:让数据驱动界面

这一课我们把客户数据放进 State,让表格和徽章根据这些数据来渲染。这也是学习 Reflex 中最重要的概念——Var 的一课。

3-1. 定义数据结构:dataclass(5 分钟)

import dataclasses


@dataclasses.dataclass
class User:
    name: str
    email: str
    gender: str
  • 这是规定“一位客户有哪些字段”的“设计图”。用 User(name="...", email="...", gender="...") 来创建。
  • 用字典({"name": ...})也可以,但用 dataclass 的话,编辑器能帮你发现字段名的拼写错误,在界面代码里也能像 user.name 这样用点号访问。

3-2. State 类(10 分钟)

class State(rx.State):
    users: list[User] = [
        User(name="Danilo Sousa", email="danilo@example.com", gender="Male"),
        User(name="Zahra Ambessa", email="zahra@example.com", gender="Female"),
    ]
  • 继承 rx.State 的类中的类变量,就是状态变量(state var)。这里写的值是初始值。
  • 类型注解(: list[User])是必需的。Reflex 根据类型来决定发送给浏览器的格式(JSON)以及可以使用哪些方法。
  • State 保存在服务器内存中,每个浏览器会话各有一份。你添加的客户别人看不到;而且它不是数据库,所以也不会被永久保存。永久保存会在第6课的扩展作业中讨论。

3-3. Var:不是“值”,而是“发给界面的表达式”(15 分钟)

第1课中我们说过“界面函数只在应用启动时执行一次”。那么在界面函数里使用 State.users,得到的是什么呢?实际打印出来看看:

>>> type(State.users).__name__
'ArrayCastedVar'
>>> print(State.users.length())
reflex___state____state__tutorial_261019___tutorial_261019____state.users_rx_state_.length

得到的不是客户列表,而是一段 JavaScript 表达式。这就是 Var。界面函数执行时,还没有用户,也没有数据,所以它只是先立下一个约定:“以后在浏览器里再读取这个值”。

因此,有些 Python 语法不能用在 Var 上。下面是 Reflex 0.10 中实际出现的错误及替代写法:

想做的事不能用的代码出现的错误Reflex 的写法
计数len(State.users)TypeError: object of type 'ArrayCastedVar' has no len()State.users.length()
条件分支"a" if State.n > 1 else "b"VarTypeError: Cannot convert Var ... to boolrx.cond(State.n > 1, "a", "b")
循环for u in State.users:VarTypeError: Cannot iterate over Var ...rx.foreach(State.users, show_user)
复杂的数据处理在界面函数中计算—在事件或 @rx.var(computed var)中计算

反过来,Var 之间的比较和算术运算(State.page + 1)、在 f-string 中嵌入 Var(f"共 {State.total} 人")都没问题,因为这些运算本身会被翻译成 JavaScript 表达式。

讲师笔记 — 这张表是本课程最重要的内容。初学者在 Reflex 中遇到的错误,大部分都出自这里。录视频时推荐这样安排:故意写 len(State.users) 展示报错画面,抛出“为什么不行?”的问题,再用上面的 print 结果来解答。

现在把页头里的临时徽章换成真实的客户数。

rx.badge(
    State.users.length(),     # 用 Var 代替 "2"
    variant="soft",
    color_scheme="gray",
    radius="full",
),

3-4. 渲染一行的函数:show_user(5 分钟)

def show_user(user: User):
    return rx.table.row(
        rx.table.cell(user.name),
        rx.table.cell(user.email),
        rx.table.cell(user.gender),
        style={"_hover": {"bg": rx.color("gray", 3)}},
        align="center",
    )
  • 类型虽然写的是 User,但实际传进来的是指向 User 的 Var。user.name 也会变成“读取这一行客户的 name”的表达式。正因为用 dataclass 声明了字段,才能用点号访问。
  • style={"_hover": {...}} 是鼠标悬停时的样式。像 _hover、_focus 这样以 _ 开头的键,对应 CSS 中 :hover 之类的状态选择器。

3-5. 表格与 rx.foreach(10 分钟)

在页头下方、卡片内部,把表格作为第二个子元素放进去。

rx.box(
    rx.table.root(
        rx.table.header(
            rx.table.row(
                rx.table.column_header_cell("Name"),
                rx.table.column_header_cell("Email"),
                rx.table.column_header_cell("Gender"),
            )
        ),
        rx.table.body(rx.foreach(State.users, show_user)),
        variant="ghost",
        size="3",
        width="100%",
    ),
    overflow_x="auto",                                   # 窄屏时横向滚动
    width="100%",
    border_top=f"1px solid {rx.color('slate', 4)}",
    border_bottom=f"1px solid {rx.color('slate', 4)}",
    padding_x="12px",
),
  • 表格结构:root > header(标题行)+ body(数据行)> row > cell,分别对应 HTML 的 <table>、<thead>、<tbody>、<tr>、<td>。
  • rx.foreach(列表 Var, 函数) 会在浏览器中对列表的每一项应用该函数。注意只传函数名,不要调用它(是 show_user,而不是 show_user())。
  • 而像标题行这样固定不变的列表,可以直接用 Python 的 for,因为它的值在编译时就已经确定了。例如:*[rx.table.column_header_cell(h) for h in ["Name", "Email", "Gender"]]

在浏览器中确认 — 卡片里出现了包含 2 位客户的表格,徽章上的 2 现在来自 State.users.length()。鼠标悬停在某一行上时,背景会变成浅灰色。

localhost:3000

运行效果

Customers

2

Your customer directory and audience breakdown.

NameEmailGender
Danilo Sousadanilo@example.comMale
Zahra Ambessazahra@example.comFemale
第3课完成:State 中的 2 位客户渲染成了表格

动手练习

  1. 在初始值中再加一位客户,确认徽章数字变成 3。
  2. 用 rx.cond 实现:客户数为 0 时,不显示表格,而是显示“还没有客户”。提示:rx.cond(State.users.length() > 0, 表格, rx.text(...))
  3. 故意写一次 len(State.users),亲自读一读错误信息。

检查点

  • 表格中显示 2 位客户,徽章显示 2。
  • 能解释什么是 Var,以及为什么不能用 len/if/for。
  • 知道为什么传给 rx.foreach 的函数不能加括号调用。

← 上一课

第2课 · 用组件绘制界面

下一课 →

第4课 · 事件与表单:添加客户

订阅新课时和新课程通知

本课程新增课时或推出后续课程时,我们会发邮件通知你。

收集项目:电子邮箱 · 用途:本课程的新课时和上线通知 · 保存期限:直到你要求删除。不会用于其他用途,也不会提供给他人。回复任意通知邮件,我们会立即删除。

问答

关于本课有任何疑问都可以在这里留言。所有语言版本页面的提问会汇集在一起。

以纯文本显示,不支持链接和格式。

R

ReflexKR

动手学 Python 和 Reflex。所有示例均已在 Reflex 0.10.0 上实际运行验证。

ReflexKR 免费,没有横幅广告。如果对你有帮助,欢迎请我们喝杯咖啡。 ☕ 请我们喝杯咖啡

联盟链接与赞助说明
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex