组件工坊:Reflex 组件库 100 例
·
课程概览
布局
·
Box
·
Flex
·
Stack
·
Grid
·
Container
·
Section
·
Center
·
Spacer
·
Separator
·
Card
·
Inset
·
Aspect Ratio
·
Fragment
排版
·
Text
·
Heading
·
Link
·
Code
·
Markdown
·
Blockquote
·
Quote
·
Strong
·
Em
·
Kbd
表单
·
Button
·
Input
·
Text Area
·
Checkbox
·
Switch
·
Radio Group
·
Select
·
Slider
·
Form
·
Upload
数据展示
·
Badge
·
Avatar
·
Icon
·
Callout
·
List
·
Data List
·
Code Block
·
Progress
·
Spinner
·
Scroll Area
·
Moment
展开与切换
·
Tabs
·
Accordion
·
Segmented Control
浮层
·
Tooltip
·
Popover
·
Hover Card
·
Dialog
·
Alert Dialog
·
Drawer
·
Dropdown Menu
·
Context Menu
·
Toast
动态渲染
·
Cond
·
Match
·
Foreach
·
Auto Scroll
媒体
·
Image
·
Audio
·
Video
表格与数据网格
·
Table
·
Data Table
·
Data Editor
图表
·
Area Chart
·
Bar Chart
·
Line Chart
·
Composed Chart
·
Pie Chart
·
Radar Chart
·
Radial Bar Chart
·
Scatter Chart
·
Funnel Chart
·
Treemap
·
Sankey Chart
·
Error Bar
图表部件
·
Axis
·
Cartesian Grid
·
Chart Tooltip
·
Legend
·
Label
·
Reference
·
Brush
其他图表库
·
Plotly
·
Pyplot
HTML 元素
·
HTML
·
HTML Text
·
HTML Layout
·
HTML Forms
·
HTML Media
·
HTML Tables
·
SVG
其他工具
·
Theme
·
Skeleton
·
Clipboard
·
Html Embed
·
Script
·
Memo
rx.foreach官方文档
工坊订单
请做一个待办清单。可以添加新的待办,做完的事点“Done”就能从列表里删掉。
rx.foreach(列表, 函数) 遍历 State 中的列表·元组·dict,把函数为每一项生成的组件依次排开。列表一变,界面就会立即重绘。Python 的 for 只在构建页面时执行一次,所以不能用于 State 中的列表。
State 变量用 rx.foreach,不变的常量用 Python 的列表·字典推导式。
#E5484D
#12A594
#3E63DD
#AD5700
#F76B15
#8E4EC6
class ForeachColorState(rx.State):
colors: list[str] = ["#E5484D", "#12A594", "#3E63DD", "#AD5700", "#F76B15", "#8E4EC6"]
def foreach_color_swatch(label: rx.Var[str | int], color: rx.Var[str]):
return rx.box(
rx.text(label, color="white", weight="medium"),
bg=color,
padding_y="0.5em",
padding_x="0.75em",
min_width="5.5em",
text_align="center",
border_radius="0.375rem",
)
def foreach_colored_box(color: rx.Var[str]):
return foreach_color_swatch(color, color)
rx.grid(
rx.foreach(ForeachColorState.colors, foreach_colored_box),
columns="2",
spacing="2",
)函数收到的 color 不是 Python 字符串,而是 rx.Var[str]。所以可以直接放进子元素或属性值(bg=color),但不能用 Python 的 if 或字符串方法(条件请用 rx.cond)。
rx.foreach 没有外观属性,那就改改列表吧。点徽章会删除该项,Add 会添加新项。想把某一项的值传给事件,就写成 on_click=State.remove(f) 这样。
2 items
FOREACH_FRUIT_POOL = ["apple", "banana", "cherry", "grape", "kiwi", "mango", "pear", "plum"]
class ForeachLiveState(rx.State):
fruits: list[str] = ["apple", "banana"]
@rx.event
def add(self):
for f in FOREACH_FRUIT_POOL:
if f not in self.fruits:
self.fruits.append(f)
return
@rx.event
def remove(self, fruit: str):
if fruit in self.fruits:
self.fruits.remove(fruit)
@rx.event
def reset_fruits(self):
self.fruits = ["apple", "banana"]
rx.vstack(
rx.hstack(
rx.foreach(
ForeachLiveState.fruits,
lambda f: rx.badge(f, rx.icon("x", size=12), on_click=ForeachLiveState.remove(f), cursor="pointer", size="2"),
),
wrap="wrap",
),
rx.hstack(
rx.button("Add", on_click=ForeachLiveState.add, size="1"),
rx.button("Reset", on_click=ForeachLiveState.reset_fruits, size="1", variant="soft", color_scheme="gray"),
rx.text(ForeachLiveState.fruits.length(), " items", size="1", color_scheme="gray"),
align="center",
),
)| 参数 | 取值 | 用途 |
|---|---|---|
第一个(iterable) | 列表·元组·dict Var | 要遍历的列表,通常是 State 变量或计算变量 |
第二个(render_fn) | 函数 (item) 或 (item, index) | 用一项生成一个组件。第二个参数是从 0 开始的序号 |
函数接收两个参数时,第二个参数就是序号(rx.Var[int],从 0 开始)。色块沿用第一个示例中的 foreach_color_swatch(下面的 dict 示例也一样)。
0
1
2
3
class ForeachIndexState(rx.State):
colors: list[str] = ["#E5484D", "#12A594", "#3E63DD", "#AD5700"]
def foreach_colored_box_index(color: rx.Var[str], index: rx.Var[int]):
return foreach_color_swatch(index, color)
rx.grid(
rx.foreach(ForeachIndexState.colors, lambda color, index: foreach_colored_box_index(color, index)),
columns="2",
spacing="2",
)在 rx.foreach 里再用 rx.foreach,就能绘制二维列表。这时 State 变量的类型要像 list[list[str]] 这样完整写出。Reflex 需要知道内层元素的类型才能遍历子列表,也能在浏览器报错之前发现写错的代码。
class ForeachNestedState(rx.State):
numbers: list[list[str]] = [["1", "2", "3"], ["4", "5", "6"], ["7", "8", "9"]]
def foreach_display_row(row: rx.Var[list[str]]):
return rx.hstack(
rx.foreach(
row,
lambda item: rx.box(item, border=f"1px solid {rx.color('gray', 8)}", padding="0.5em", min_width="2.2em", text_align="center"),
),
)
rx.vstack(rx.foreach(ForeachNestedState.numbers, foreach_display_row))传入 dict 时,函数每次收到一个 (键, 值) 对。color[0] 是键,color[1] 是值。无论键原本是什么类型(这里是 int),在函数里都会变成字符串。
1
2
3
class ForeachSimpleDictState(rx.State):
color_chart: dict[int, str] = {1: "#3E63DD", 2: "#E5484D", 3: "#12A594"}
def foreach_display_color(color: rx.Var[tuple[str, str]]):
# color is a key-value pair such as ("1", "#3E63DD").
return foreach_color_swatch(color[0], color[1])
rx.grid(
rx.foreach(ForeachSimpleDictState.color_chart, foreach_display_color),
columns="3",
spacing="2",
)如果 dict 的值是列表,就再用 rx.foreach 遍历这个值。下面在每个键颜色下方排出与之配对的颜色。
#8E4EC6
#E5484D
#3E63DD
#F76B15
#AD5700
#E5484D
#12A594
#3E63DD
#AD5700
class ForeachComplexDictState(rx.State):
color_chart: dict[str, list[str]] = {
"#8E4EC6": ["#E5484D", "#3E63DD"],
"#F76B15": ["#AD5700", "#E5484D"],
"#12A594": ["#3E63DD", "#AD5700"],
}
def foreach_display_colors(color: rx.Var[tuple[str, list[str]]]):
return rx.vstack(
foreach_color_swatch(color[0], color[0]),
rx.hstack(rx.foreach(color[1], lambda x: foreach_color_swatch(x, x))),
align="center",
spacing="2",
)
rx.grid(
rx.foreach(ForeachComplexDictState.color_chart, foreach_display_colors),
columns="3",
spacing="4",
)如果列表是不会变的常量,就不需要 rx.foreach。在构建页面时让 Python 遍历一次、把组件展开即可。每一项都是真正的 Python 值,可以用字符串方法和 if。
rx.hstack(
*[rx.badge(size, variant="soft") for size in ["S", "M", "L", "XL"]],
)待办是 {"id", "text"} dict 的列表(像官方文档那样用 dataclass 列表也可以)。每一项都给 key=item["id"],这样删掉一项时,其余各行保持不变。Done 把该项的 id 传给处理器,处理器生成去掉这个 id 的新列表。输入通过表单接收,按 Enter 也能添加。
Write Code
Sleep
Have Fun
class ForeachTodoState(rx.State):
items: list[dict[str, str]] = [
{"id": "1", "text": "Write Code"},
{"id": "2", "text": "Sleep"},
{"id": "3", "text": "Have Fun"},
]
next_id: int = 4
@rx.event
def add_item(self, form_data: dict):
text = form_data.get("new_item", "").strip()[:40]
if text and len(self.items) < 8:
self.items = self.items + [{"id": str(self.next_id), "text": text}]
self.next_id += 1
@rx.event
def finish_item(self, item_id: str):
self.items = [item for item in self.items if item["id"] != item_id]
rx.vstack(
rx.heading("Todos", size="4"),
rx.form(
rx.hstack(
rx.input(name="new_item", placeholder="Add a todo...", flex="1"),
rx.button("Add", type="submit"),
width="100%",
),
on_submit=ForeachTodoState.add_item,
reset_on_submit=True,
width="100%",
),
rx.divider(),
rx.list.ordered(
rx.foreach(
ForeachTodoState.items,
lambda item: rx.list.item(
rx.hstack(
rx.button("Done", on_click=ForeachTodoState.finish_item(item["id"]), size="1", variant="soft"),
rx.text(item["text"]),
align="center",
),
key=item["id"],
),
),
),
width="100%",
max_width="360px",
padding="1em",
border_radius="0.5em",
background=rx.color("gray", 3),
)工坊笔记
rx.foreach(State.列表, 函数)。常量列表用 Python 推导式。
函数收到的项是 Var。用 rx.cond 代替 Python 的 if,取值用 item["key"]。
用 (item, index) 也能拿到序号。dict 是 (键, 值) 对,键会变成字符串。
嵌套列表要把类型写全,如 list[list[str]]。
会增删的列表要给 key=唯一值。
订阅新课时和新课程通知
本课程新增课时或推出后续课程时,我们会发邮件通知你。
问答
关于本课有任何疑问都可以在这里留言。所有语言版本页面的提问会汇集在一起。