组件工坊: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.auto_scroll官方文档
工坊订单
请做一个客服聊天窗口。有新消息时要跟着滚到最底部,但如果用户正往上翻看之前的对话,就不要把他拉下去。
rx.auto_scroll 是一个在新内容加入时自动滚到底部的盒子(div)。用于聊天、日志、动态流这类内容不断往下堆积、需要始终显示最新内容的地方。不必自己写处理滚动位置的代码。
class AutoScrollBasicState(rx.State):
messages: list[str] = ["Initial message"]
count: int = 1
@rx.event
def add_message(self):
self.count += 1
self.messages = (self.messages + [f"New message #{self.count}"])[-50:]
rx.vstack(
rx.auto_scroll(
rx.foreach(
AutoScrollBasicState.messages,
lambda message: rx.box(
message,
padding="0.5em",
border_bottom=f"1px solid {rx.color('gray', 4)}",
width="100%",
),
),
height="200px",
width="300px",
border=f"1px solid {rx.color('gray', 6)}",
border_radius="8px",
),
rx.button("Add Message", on_click=AutoScrollBasicState.add_message),
width="300px",
align_items="center",
)每点一次 Add Message 就会添加一条消息;盒子开始溢出后,它会自动往下滚,让新消息保持可见。
rx.auto_scroll 基于 rx.el.div,接受 div 的所有属性和样式。它是滚动盒子,所以 height 最重要。下面的盒子里有二十行,一开始就能看到最后一行(Line 20)。把高度调小让它溢出,底部依然保持可见。
试着改属性
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10
Line 11
Line 12
Line 13
Line 14
Line 15
Line 16
Line 17
Line 18
Line 19
Line 20
height
padding
radius
rx.auto_scroll(
*[rx.text("Line " + str(i), size="2") for i in range(1, 21)],
height="160px",
padding="8px",
border_radius="8px",
border=f"1px solid {rx.color('gray', 6)}",
width="260px",
)| 属性 | 取值 | 默认值 | 用途 |
|---|---|---|---|
height | CSS 长度 | 无 | 滚动盒子的高度。不设的话会随内容伸长,不会出现滚动条 |
width | CSS 长度 | 无 | 宽度 |
overflow | CSS 值 | "auto" | 溢出内容的处理方式,默认滚动 |
padding, border, border_radius | CSS 值 | 无 | 内边距、边框、圆角 |
id | 字符串 | 自动 | 不另行指定时会自动加上唯一 id |
| 其他 div 属性 | title, role, on_click … | 与 rx.el.div 相同 |
添加内容时,只有在下面两种情况下才会滚到底部。
所以用户往上翻看旧内容时,不会被强行拉下去。把下面的日志盒子往上滚,再点 Add 10 试试,位置不会变。滚回底部后再点,它就会跟着往下滚。
import random
class AutoScrollLogState(rx.State):
lines: list[str] = []
count: int = 0
@rx.event
def add(self, n: int):
levels = ["INFO", "INFO", "INFO", "WARN", "ERROR"]
new = []
for _ in range(n):
self.count += 1
new.append(f"{self.count:04d} {random.choice(levels)} request handled")
self.lines = (self.lines + new)[-100:]
@rx.event
def clear(self):
self.lines = []
self.count = 0
rx.vstack(
rx.auto_scroll(
rx.foreach(AutoScrollLogState.lines, lambda line: rx.text(line, size="1", font_family="var(--code-font-family)")),
height="160px",
width="100%",
padding="8px 10px",
background=rx.color("gray", 2),
border=f"1px solid {rx.color('gray', 6)}",
border_radius="8px",
),
rx.hstack(
rx.button("Add 1", on_click=AutoScrollLogState.add(1), size="1"),
rx.button("Add 10", on_click=AutoScrollLogState.add(10), size="1", variant="soft"),
rx.button("Clear", on_click=AutoScrollLogState.clear, size="1", variant="soft", color_scheme="gray"),
),
width="100%",
max_width="420px",
)给 rx.auto_scroll 设置 display="flex" 和 flex_direction="column",把气泡竖向堆叠,再按发送者用 rx.cond 切换对齐方式和颜色。发送消息后,我的话和回复会一起加入,窗口跟着往下滚。如果正往上翻着看,就保持不动。
class AutoScrollChatState(rx.State):
messages: list[dict[str, str]] = [{"who": "bot", "text": "Hi! Ask me about your order."}]
@rx.event
def send(self, form_data: dict):
text = form_data.get("text", "").strip()[:200]
if not text:
return
reply = {"who": "bot", "text": f"Got it: {text}"}
self.messages = (self.messages + [{"who": "me", "text": text}, reply])[-40:]
rx.vstack(
rx.auto_scroll(
rx.foreach(
AutoScrollChatState.messages,
lambda m: rx.flex(
rx.box(
m["text"],
padding="6px 10px",
border_radius="12px",
max_width="80%",
background=rx.cond(m["who"] == "me", rx.color("indigo", 9), rx.color("gray", 4)),
color=rx.cond(m["who"] == "me", "white", rx.color("gray", 12)),
),
justify=rx.cond(m["who"] == "me", "end", "start"),
width="100%",
),
),
display="flex",
flex_direction="column",
gap="6px",
height="240px",
width="100%",
padding="10px",
border=f"1px solid {rx.color('gray', 6)}",
border_radius="10px",
),
rx.form(
rx.hstack(
rx.input(name="text", placeholder="Type a message", flex="1", auto_complete=False),
rx.button(rx.icon("send", size=16), type="submit", aria_label="Send"),
width="100%",
),
on_submit=AutoScrollChatState.send,
reset_on_submit=True,
width="100%",
),
width="100%",
max_width="360px",
)工坊笔记
rx.auto_scroll(...) 是一个有新内容就跟到底部的 div。
一定要给 height。overflow="auto" 默认已经设置。
只有在接近底部(50px)时,或新出现滚动条时才会往下滚。
不会把正在往上翻看的用户拉下去。适合聊天·日志·动态流。
订阅新课时和新课程通知
本课程新增课时或推出后续课程时,我们会发邮件通知你。
问答
关于本课有任何疑问都可以在这里留言。所有语言版本页面的提问会汇集在一起。