R

ReflexKR

Reflex 官方文档

动手掌握 Reflex 基础

·

课程概览

1

一点就变:State 与事件

2

时隐时现:条件渲染

3

绘制列表:rx.foreach

4

为什么 if 不行?编译时与运行时

5

打扮界面:组件、props 与样式

6

应用、页面,以及水果篮

动手掌握 Reflex 基础
第4课

时间 0:18–0:28

为什么 if 不行?编译时与运行时

第2课用 rx.cond 代替了 if,第3课用 rx.foreach 代替了 for。明明写的是 Python,为什么不能直接用 Python 语法?这一课把原因讲透,你就能一下子明白在 Reflex 中遇到的大多数错误是怎么来的。

4-1. 代码执行的两个时间点(3 分钟)

Reflex 应用的代码会在两个不同的时间点执行。

编译时运行时
何时应用启动时执行一次应用运行期间持续执行
执行什么界面函数(show_login、render_item …)事件处理器(increment、toggle_login …)
在哪里Python 代码被转换为 JavaScript(React)代码服务器上的 Python
State 的值还不知道有真实的值

界面函数在应用启动时被翻译成 JavaScript,再发送到浏览器。翻译的时候,还不知道哪个用户会点什么,所以界面函数里的 LoginState.logged_in 并不是真正的 True/False,而是一个"之后在浏览器里才会填入的占位"。这个占位就是 Var。

反过来,事件处理器不会被翻译,而是以 Python 原样在服务器上执行。所以在处理器里,任何 Python 代码和库都可以使用。

4-2. 处理器里是真正的 Python(2 分钟)

下面的处理器既用了 if,又调用了定义在 State 外部的函数。因为它是在运行时于服务器上执行的,所以完全没问题。

def check_even(num: int):
    return num % 2 == 0


class MyState3(rx.State):
    count: int = 0
    text: str = "even"

    @rx.event
    def increment(self):
        # Use any Python code within state.
        # Even reference functions defined outside the state.
        if check_even(self.count):
            self.text = "even"
        else:
            self.text = "odd"
        self.count += 1


def count_and_check():
    return rx.box(
        rx.heading(MyState3.text, as_="h2"),
        rx.button("Increment", on_click=MyState3.increment),
    )

localhost:3000

动手试试

even

每次点击,处理器里的 Python if 都会选出 even 或 odd。

界面函数里也不是不能写 Python,但只能用于编译时就已经确定值的东西(不涉及 State var 的部分)。下面的 range(5) 和 check_even(i) 在应用启动时就已经计算完毕。

def show_numbers():
    return rx.vstack(*[rx.text(f"{i} is {'even' if check_even(i) else 'odd'}") for i in range(5)])

localhost:3000

运行效果

0 is even

1 is odd

2 is even

3 is odd

4 is even

这五行在编译时就已计算完毕,应用运行期间不会改变。

4-3. 界面代码中不能做的三件事(2 分钟)

State var 在编译时还没有值,所以在界面函数中写下面这些代码都会报错。

用 if 判断 Var 的值:还不知道它是真是假。用来选择 props 的值时也一样。

class BadState(rx.State):
    count: int = 0


def count_if_even():
    return rx.box(
        rx.heading("Count: ", as_="h2"),
        # This will raise a compile error, as BadState.count is a var and not known at compile time.
        rx.text(BadState.count if BadState.count % 2 == 0 else "Odd"),
        # Using an if statement with a var as a prop will NOT work either.
        rx.text("hello", color="red" if BadState.count % 2 == 0 else "blue"),
    )

用 for 遍历列表 Var:还不知道里面有几个元素。

class BadState(rx.State):
    items: list[str] = ["Apple", "Banana", "Cherry"]


def loop_over_list():
    return rx.box(
        # This will raise a compile error, as BadState.items is a list and not known at compile time.
        *[rx.text(item) for item in BadState.items]
    )

把 Var 传给 len() 这类 Python 函数:要统计字数的字符串还不存在。

class BadTextState(rx.State):
    text: str = "Hello world"


def format_text():
    return rx.box(
        # Python operations such as `len` will not work on state vars.
        rx.text(len(BadTextState.text)),
    )

4-4. 解决办法:Var 运算(3 分钟)

那么,要在界面上显示"偶数显示 Even,奇数显示 Odd"该怎么办?Reflex 准备了可用于 Var 的 Var 运算。对 Var 使用 %、==、> 等运算符,得到的结果也是 Var,真正的计算要等到值传进浏览器之后才进行。

class CountEvenState(rx.State):
    count: int = 0

    @rx.event
    def increment(self):
        self.count += 1


def count_if_even():
    return rx.box(
        rx.heading("Count: ", CountEvenState.count, as_="h2"),
        rx.cond(
            # Here we use the `%` and `==` var operations to check if the count is even.
            CountEvenState.count % 2 == 0,
            rx.text("Even"),
            rx.text("Odd"),
        ),
        rx.button("Increment", on_click=CountEvenState.increment),
    )

localhost:3000

动手试试

Count: 0

Even

rx.cond 接收 Var 运算 % 和 == 的结果,选出 Even 或 Odd。

现在可以用一张表总结第1~3课用到的工具为什么必不可少。

想做的事界面代码中不能用改用
根据条件显示不同界面if / elserx.cond(条件, 为真时, 为假时)
遍历列表for、列表推导式rx.foreach(列表, 函数)
求长度len(x)x.length()
计算、比较把 Var 传给 Python 函数%、==、> 等 Var 运算
复杂计算界面函数里的 Python在事件处理器中计算后存入 State

小贴士 — 拿不准的时候,问自己一句:"这段代码是什么时候执行的?"如果在界面函数里,那就是编译时,Var 还只是个占位;如果在处理器里,那就是运行时,拿到的是真实的值。

课后练习

  1. 修改 4-3 中的 format_text,让它显示字符数。提示:BadTextState.text.length()。
  2. 在 count_if_even 中,当 count 大于等于 10 时显示 "Big!"。提示:rx.cond(CountEvenState.count >= 10, ...)。
  3. 比较一下像 MyState3 那样在处理器里计算的方式,和像 CountEvenState 那样使用 Var 运算的方式。哪一种需要的 State 变量更少?

本课检查清单

  • 能说出界面函数和事件处理器分别在何时、何处执行。
  • 能解释为什么在界面代码中不能对 State var 使用 if、for、len()。
  • 知道如何用 Var 运算、rx.cond、rx.foreach 实现同样的效果。

← 上一课

第3课 · 绘制列表:rx.foreach

下一课 →

第5课 · 打扮界面:组件、props 与样式

订阅新课时和新课程通知

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

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

问答

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

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

R

ReflexKR

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

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

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

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

Built with Reflex