组件工坊: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.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",
)把元素的 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,所以过大的图片会被过滤掉。
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, ...] 不用包裹也能只监听特定元素。
订阅新课时和新课程通知
本课程新增课时或推出后续课程时,我们会发邮件通知你。
问答
关于本课有任何疑问都可以在这里留言。所有语言版本页面的提问会汇集在一起。