先别急着看讲解,动手点一点。点击下面的按钮,数字每次加 1。学完这一课,你就能讲清楚这十几行代码是怎么运作的。
import reflex as rx
class CounterState(rx.State):
count: int = 0
@rx.event
def increment(self):
self.count += 1
def counter_increment():
return rx.hstack(
rx.heading(CounterState.count, as_="h2"),
rx.button("Increment", on_click=CounterState.increment),
)localhost:3000
动手试试这段代码分为三部分。
| 部分 | 代码 | 作用 |
|---|---|---|
| State | class CounterState(rx.State) | 存放会变化的数据(count)的容器 |
| 事件处理器 | def increment(self) | 修改数据的函数 |
| 事件触发器 | on_click=CounterState.increment | "点击时调用这个函数"的绑定 |
点击按钮后,increment 在服务器上执行;count 一变,Reflex 就会自动重新渲染用到这个值的那部分界面。整个过程中,没有一行代码是直接去改界面的。
应用里总有一些会随时间变化的数据,比如计数器的数字、是否已登录、购物车列表等。在 Reflex 中,这类数据放在 State 类里。
rx.State 的类,在里面写上变量。这些变量称为 Var(state var)。count: int),也可以设置默认值(= 0)。要在界面中使用 Var,需要像 MyState.count 这样通过类名来引用。它既可以作为子组件放进去,也可以作为 props 的值传入。
class MyState(rx.State):
count: int = 0
color: str = "red"
def counter():
return rx.hstack(
# The heading `color` prop is set to the `color` var in MyState.
rx.heading("Count: ", as_="h2", color=MyState.color),
# The `count` var in `MyState` is passed as a child to the heading component.
rx.heading(MyState.count, as_="h2"),
)localhost:3000
运行效果同一个 Var 可以在多个组件中使用。值一旦变化,所有用到这个 Var 的地方都会一起更新。
小贴士 — 能修改 State 的只有事件处理器。不能在界面代码里像 MyState.count = 5 这样直接赋值。
State 中定义的、用来修改数据的方法称为事件处理器。像 on_click 这样组件自带的特殊 props 称为事件触发器。把触发器和处理器连接起来,界面就能响应用户的操作。
强烈建议在处理器上方加上 @rx.event。有了这个装饰器,编辑器和类型检查器就能帮你确认"这个处理器该传几个参数、分别是什么类型",提前发现错误。
处理器也能像普通函数一样接收参数。下面用同一个处理器,做出"加 1"和"加 5"两个按钮。
class CounterState2(rx.State):
count: int = 0
@rx.event
def increment(self, amount: int):
self.count += amount
def counter_variable():
return rx.hstack(
rx.heading(CounterState2.count, as_="h2"),
rx.button("Increment by 1", on_click=lambda: CounterState2.increment(1)),
rx.button("Increment by 5", on_click=lambda: CounterState2.increment(5)),
)localhost:3000
动手试试lambda 包了一层,写成 lambda: CounterState2.increment(1),明确表达"点击时传入 1 来调用"的意思。on_click=CounterState2.increment(1) 效果也完全一样。这行代码并不会立即执行处理器,而只是生成一条"点击时以 amount=1 执行"的事件信息。处理器的代码要等到点击按钮时才在服务器上执行。on_click 不会给处理器传任何值,但有些触发器会传值。on_blur 会在输入框失去焦点时(点击别处或按下 Tab 键),把输入的文字传给处理器。
class TextState(rx.State):
text: str = ""
@rx.event
def update_text(self, new_text: str):
self.text = new_text
def text_input():
return rx.vstack(
rx.heading(TextState.text, as_="h2"),
rx.input(default_value=TextState.text, on_blur=TextState.update_text),
)localhost:3000
动手试试小贴士 — 处理器的参数个数必须和触发器传入的值的个数一致。on_blur 传入一个值,所以 update_text 也只接收 new_text 一个参数。个数不一致就会报错。
CounterState 添加一个 decrement 处理器,再做一个让数字每次减 1 的按钮。counter_variable 添加一个 "Reset" 按钮,把 count 重置为 0。能不能用接收参数的处理器来实现?on_blur 换成 on_change 试试。这样每输入一个字,标题都会跟着变。类名.变量名 引用 Var。on_click 传入带参数的处理器时,处理器并不会立即执行。订阅新课时和新课程通知
本课程新增课时或推出后续课程时,我们会发邮件通知你。
问答
关于本课有任何疑问都可以在这里留言。所有语言版本页面的提问会汇集在一起。