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 例
其他工具

Clipboard

rx.clipboard

官方文档

工坊订单

请在问题反馈表单上做一个区域,用户只要粘贴屏幕截图,图片就会立即附上。

rx.clipboard 接收粘贴(paste)事件,把粘贴的内容按类型交给 State。不仅能接收文字,也能接收图片这类二进制数据。 它是一个不在页面上绘制任何东西的透明组件,监听被它包住的子元素中发生的粘贴。从 Reflex 0.5.6 起提供。

class ClipboardBasicState(rx.State):
    items: list[str] = []

    @rx.event
    def on_paste(self, data: list[tuple[str, str]]):
        self.items = [f"{mime_type}: {item[:60]}" for mime_type, item in data]


rx.vstack(
    rx.clipboard(
        rx.input(placeholder="Copy some text, then paste here"),
        on_paste=ClipboardBasicState.on_paste,
    ),
    rx.foreach(ClipboardBasicState.items, lambda line: rx.code(line, size="1")),
    width="100%",
    max_width="420px",
)

粘贴试试

rx.clipboard 没有可见的属性,所以这里不用实验台,而是用一个响应粘贴的示例来演示。 粘贴文字会得到 text/plain;粘贴从网页复制的文字还会同时带上 text/html;粘贴图片则会得到 image/png 之类的类型。

Paste events: 0

class ClipboardTypesState(rx.State):
    count: int = 0
    types: list[str] = []

    @rx.event
    def on_paste(self, data: list[tuple[str, str]]):
        self.count += 1
        self.types = [mime_type for mime_type, _ in data]


rx.card(
    rx.clipboard(
        rx.text_area(placeholder="Paste text, an image, or a copied web page", rows="3"),
        on_paste=ClipboardTypesState.on_paste,
    ),
    rx.text("Paste events: ", ClipboardTypesState.count, size="2", margin_top="8px"),
    rx.flex(rx.foreach(ClipboardTypesState.types, lambda t: rx.badge(t)), spacing="2", wrap="wrap", margin_top="6px"),
    max_width="420px",
)
属性取值默认值用途
on_paste事件处理器无接收 (MIME 类型, 数据) 元组的列表
targets元素 id 列表子元素;没有子元素时为整个文档要监听粘贴的元素
.stop_propagation事件动作无不再传给外层的粘贴处理器
.prevent_default事件动作无阻止内容真正粘贴进输入框的默认行为

数据的形式

on_paste 收到的 data 是 (mime_type, data) 元组的列表。文字原样以字符串传来, 图片这类二进制数据则以 base64 编码的 data URI(data:image/png;base64,...)传来。这个字符串可以直接放进 rx.image 的 src; 如果服务器上需要字节,可以用 Python 的 urllib.request.urlopen(data_uri).read() 解开。

在整个页面接收

不放子元素、只写 rx.clipboard(),它就会挂到文档的 paste 事件上,在页面任何地方粘贴都会触发。 如果在本页这样放,连其他示例里的粘贴也会全部被捕获,所以官方文档的示例只以代码展示。

class ClipboardPasteState(rx.State):
    @rx.event
    def on_paste(self, data: list[tuple[str, str]]):
        for mime_type, item in data:
            yield rx.toast(f"Pasted {mime_type} data: {item}")


def clipboard_example():
    return rx.fragment(
        rx.clipboard(on_paste=ClipboardPasteState.on_paste),   # no children: listens for paste on the whole document
        "Paste Content Here",
    )

限定范围的粘贴

想只在特定元素上接收粘贴,就用 rx.clipboard 包住那个元素。如果外层还有整个页面的处理器,就用 .stop_propagation 阻止事件向上传递。 加上 .prevent_default 后,文字不会真正粘贴进输入框。往第二个输入框里粘贴文字试试,框里仍是空的。

No image yet. Copy an image (or take a screenshot) and paste above.

class ClipboardImageState(rx.State):
    last_image_uri: str = ""

    @rx.event
    def on_paste(self, data: list[tuple[str, str]]):
        for mime_type, item in data:
            if mime_type.startswith("image/"):
                if len(item) > 2_000_000:
                    return rx.toast("This image is too large for the demo")
                self.last_image_uri = item
                break
        else:
            return rx.toast("Did not find an image in the pasted data")


rx.vstack(
    rx.clipboard(
        rx.input(placeholder="Paste Image (stop propagation)"),
        on_paste=ClipboardImageState.on_paste.stop_propagation,
    ),
    rx.clipboard(
        rx.input(placeholder="Paste Image (prevent default)"),
        on_paste=ClipboardImageState.on_paste.prevent_default,
    ),
    rx.cond(
        ClipboardImageState.last_image_uri != "",
        rx.image(src=ClipboardImageState.last_image_uri, alt="Image pasted from clipboard", max_width="240px", border_radius="6px"),
        rx.text("No image yet. Copy an image (or take a screenshot) and paste above.", size="2", color_scheme="gray"),
    ),
    width="100%",
    max_width="420px",
)

targets:不用包裹,用 id 指定

把元素的 id 交给 targets,不用包住也能只监听那个元素。包住子元素时,Reflex 会给子元素加上 id,自动填好 targets。

Pasted characters: 0

class ClipboardTargetState(rx.State):
    pasted_chars: int = 0

    @rx.event
    def on_paste(self, data: list[tuple[str, str]]):
        self.pasted_chars += sum(len(item) for mime_type, item in data if mime_type == "text/plain")


rx.vstack(
    rx.clipboard(on_paste=ClipboardTargetState.on_paste, targets=["clipboard_target_note"]),
    rx.text_area(id="clipboard_target_note", placeholder="Only this box is watched", rows="2"),
    rx.input(placeholder="This box is not watched"),
    rx.text("Pasted characters: ", ClipboardTargetState.pasted_chars, size="2"),
    width="100%",
    max_width="420px",
)

完成订单

点击虚线框让它获得焦点,再粘贴截图,图片就会附上。这个框不是输入框,所以用 tab_index=0 让它能获得焦点, 并像 .prevent_default.stop_propagation 这样把事件动作串起来。图片以 data URI 存进 State,所以过大的图片会被过滤掉。

Bug report

Click here, then paste a screenshot (Ctrl + V)

class ClipboardTicketState(rx.State):
    shot: str = ""
    note: str = ""

    @rx.event
    def on_paste(self, data: list[tuple[str, str]]):
        for mime_type, item in data:
            if mime_type.startswith("image/") and len(item) <= 2_000_000:
                self.shot = item
                return
        return rx.toast("Paste a screenshot (an image) here")

    @rx.event
    def change_note(self, value: str):
        self.note = value

    @rx.event
    def clear_shot(self):
        self.shot = ""


rx.card(
    rx.heading("Bug report", size="3"),
    rx.text_area(
        value=ClipboardTicketState.note,
        on_change=ClipboardTicketState.change_note,
        placeholder="What went wrong?",
        rows="2",
        margin_y="8px",
    ),
    rx.clipboard(
        rx.box(
            rx.cond(
                ClipboardTicketState.shot != "",
                rx.image(src=ClipboardTicketState.shot, alt="Pasted screenshot", max_height="160px"),
                rx.text("Click here, then paste a screenshot (Ctrl + V)", size="2", color_scheme="gray"),
            ),
            tab_index=0,
            padding="16px",
            border=f"2px dashed {rx.color('gray', 7)}",
            border_radius="8px",
            text_align="center",
        ),
        on_paste=ClipboardTicketState.on_paste.prevent_default.stop_propagation,
    ),
    rx.button("Remove screenshot", on_click=ClipboardTicketState.clear_shot, variant="soft", color_scheme="gray", size="1", margin_top="8px"),
    max_width="420px",
)

工坊笔记

  • rx.clipboard(子元素, on_paste=...) 监听子元素中发生的粘贴。没有子元素时监听整个文档。

  • on_paste 接收 [(mime_type, data), ...]。二进制数据是 base64 data URI。

  • data URI 可以直接用作 rx.image 的 src。

  • .stop_propagation 不传给外层处理器,.prevent_default 阻止真正的粘贴。

  • 用 targets=[id, ...] 不用包裹也能只监听特定元素。

← 上一课

其他工具 · Skeleton

下一课 →

其他工具 · Html Embed

订阅新课时和新课程通知

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

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

问答

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

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

R

ReflexKR

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

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

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

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

Built with Reflex