R

ReflexKR

Reflex 官方文档

组件工坊: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

组件工坊:Reflex 组件库 100 例
动态渲染

Auto Scroll

rx.auto_scroll

官方文档

工坊订单

请做一个客服聊天窗口。有新消息时要跟着滚到最底部,但如果用户正往上翻看之前的对话,就不要把他拉下去。

rx.auto_scroll 是一个在新内容加入时自动滚到底部的盒子(div)。用于聊天、日志、动态流这类内容不断往下堆积、需要始终显示最新内容的地方。不必自己写处理滚动位置的代码。

Initial message
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",
)
默认设置了 overflow="auto",超出高度的内容会在盒子内部滚动。
属性取值默认值用途
heightCSS 长度无滚动盒子的高度。不设的话会随内容伸长,不会出现滚动条
widthCSS 长度无宽度
overflowCSS 值"auto"溢出内容的处理方式,默认滚动
padding, border, border_radiusCSS 值无内边距、边框、圆角
id字符串自动不另行指定时会自动加上唯一 id
其他 div 属性title, role, on_click …与 rx.el.div 相同

什么时候用

  • 聊天:让对话窗口始终显示最新消息。
  • 查看日志:有新日志行时跟着往下滚。
  • 动态流:在持续更新的列表中保持新内容可见。

工作方式

添加内容时,只有在下面两种情况下才会滚到底部。

  1. 用户已经在接近底部的位置(50 像素以内)
  2. 原来没有滚动条,因为新内容才出现了滚动条

所以用户往上翻看旧内容时,不会被强行拉下去。把下面的日志盒子往上滚,再点 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 切换对齐方式和颜色。发送消息后,我的话和回复会一起加入,窗口跟着往下滚。如果正往上翻着看,就保持不动。

Hi! Ask me about your order.
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)时,或新出现滚动条时才会往下滚。

  • 不会把正在往上翻看的用户拉下去。适合聊天·日志·动态流。

← 上一课

动态渲染 · Foreach

下一课 →

媒体 · Image

订阅新课时和新课程通知

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

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

问答

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

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

R

ReflexKR

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

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

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

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

Built with Reflex