27 个版本 (11 个破坏性更新)
| 新 0.12.0 | 2024 年 8 月 14 日 |
|---|---|
| 0.10.2 | 2024 年 6 月 7 日 |
| 0.9.1 | 2024 年 2 月 28 日 |
| 0.6.0 | 2023 年 11 月 2 日 |
| 0.3.2 | 2023 年 7 月 21 日 |
#156 in 网页编程
每月 364 次下载
670KB
2K SLoC
Leptos Struct Table
轻松从结构创建 Leptos 表格组件。

功能
- 易于使用 - 但功能强大。
- 异步数据加载 - 数据异步加载。这允许从 REST API 或数据库等加载数据。
- 选择 - 可关闭或单选/多选
- 定制 - 您可以通过连接自己的用于渲染行、单元格、标题的组件来自定义表格的每个方面。有关更多信息,请参阅自定义渲染器。
- 无头 - 表格不应用默认样式。您可以完全自定义应用于表格的类。有关更多信息,请参阅类定制。
- 排序 - 可选。如果开启:点击列标题按该列排序表格。您甚至可以按多个列排序。
- 虚拟化 - 只渲染可见行。这允许处理非常大的表格。
- 分页 - 替代虚拟化,您可以分页表格。
- 缓存 - 只加载和缓存可见行。
- 编辑 - 可选。您可以提供自定义渲染器以编辑可编辑的单元格。有关更多信息,请参阅可编辑单元格。
使用方法
use leptos::*;
use leptos_struct_table::*;
#[derive(TableRow, Clone)]
#[table(impl_vec_data_provider)]
pub struct Person {
id: u32,
name: String,
age: u32,
}
fn main() {
mount_to_body(|| {
let rows = vec![
Person { id: 1, name: "John".to_string(), age: 32 },
Person { id: 2, name: "Jane".to_string(), age: 28 },
Person { id: 3, name: "Bob".to_string(), age: 45 },
];
view! {
<table>
<TableContent rows />
</table>
}
});
}
服务器端渲染
要使用 Leptos 的服务器端渲染功能,您需要将 leptos-use 作为依赖项添加到您的 Cargo.toml,然后像以下那样进行配置。
[dependencies]
leptos-use = "<current version>"
# ...
[features]
hydrate = [
"leptos/hydrate",
# ...
]
ssr = [
"leptos/ssr",
# ...
"leptos-use/ssr",
]
请参阅serverfn_sqlx 示例,了解带有 SSR 的工作项目。
数据提供者
如图初始使用示例所示,当您将 #[table(impl_vec_data_provider)] 添加到您的结构体中时,表格会自动为您生成数据提供者。然后您可以直接将一个 Vec<T> 传递给 rows 属性。内部实现了 TableDataProvider 特性,用于 Vec<T>。
要利用具有缓存功能的异步部分数据加载的完整功能,您应该实现 PaginatedTableDataProvider 特性或自己实现 TableDataProvider 特性。这样做很简单。您选择哪个特性取决于您的数据源。如果您的数据源提供分页数据,例如许多REST API的情况,则应实现 PaginatedTableDataProvider。否则,您可能需要实现 TableDataProvider。
请参阅 paginated_rest_datasource 示例 和 serverfn_sqlx 示例,以查看实现这些特性的工作演示项目。
宏选项
可以使用 #[table(...)] 属性来自定义生成的组件。以下是一些可用的选项
结构体属性
以下属性可以应用于结构体本身。
sortable- 指定表格应可排序。这使得标题可点击以控制排序。您可以在TableContent组件的sorting_mode属性中指定两种排序模式sorting_mode=SortingMode::MultiColumn(默认)允许表格按优先级排序多个列。sorting_mode=SortingMode::SingleColumn""允许表格按单个列排序。点击另一个列将简单地替换排序列。有关更多信息,请参阅 simple 示例 和 selectable 示例。
classes_provider- 指定类提供者的名称。用于快速自定义应用于表格的所有类。为了方便起见,为主要的CSS框架提供了合理的预设。有关更多信息,请参阅TableClassesProvider和 tailwind 示例。head_cell_renderer- 指定表头单元格渲染组件的名称。用于自定义表头单元格的渲染。默认为DefaultTableHeaderRenderer。有关更多信息,请参阅 custom_renderers_svg 示例。impl_vec_data_provider- 如果提供,则自动为Vec<ThisStruct>实现TableDataProvider,以便于本地数据的使用。有关更多信息,请参阅 simple 示例。row_type- 指定表格中行的类型。默认为此应用到的结构体。有关更多信息,请参阅 custom_type 示例。
字段属性
这些属性可以应用于结构体中的任何字段。
class- 指定应用于字段列中每个单元格(头和体)的类。可以与classes_provider一起使用来自定义类。head_class- 指定应用于字段列中头单元格的类。可以与classes_provider一起使用来自定义类。cell_class- 指定应用于字段列中体单元格的类。可以与classes_provider一起使用来自定义类。skip- 指定应跳过该字段。这对于不在表中显示的字段很有用。skip_sort- 仅当在结构体上设置了sortable时适用。指定该字段不应用于排序。点击其标题将不会进行任何操作。skip_header- 使字段的标题不在头行中显示。title- 指定在头单元格中显示的标题。默认为将字段名转换为标题大小写(this_field变为"This Field")。renderer- 指定单元格渲染组件的名称。用于自定义单元格的渲染。默认为DefaultTableCellRenderer。format- 快速自定义单元格格式的快捷方式,而无需创建自定义渲染器。有关更多信息,请参阅下面的 Formatting。getter- 指定一个返回字段值的函数,而不是在渲染时直接访问字段。none_value- 当Option类型为None时,指定要显示的显示值。默认为空字符串。
格式化
可以使用 format 属性来自定义单元格的格式。当您只想自定义一些基本的格式时,这是一个创建自定义渲染器的更简单替代方案。它是类型安全的,并且与应用格式的类型绑定。请参阅 CellValue 以及您要渲染的类型的相关类型,以查看选项列表
参见
功能
chrono- 为chrono包中的类型添加支持。rust_decimal- 为rust_decimal包中的类型添加支持。time- 为time包中的类型添加支持。uuid- 为uuid包中的类型添加支持。
类自定义
可以通过在结构体上使用 classes_provider 属性来轻松地自定义类。您可以指定任何实现了 TableClassesProvider 特性的类型。请参阅该特性的文档以获取更多信息。您还可以查看 TailwindClassesPreset 以了解如何实现此功能。
示例
#[derive(TableRow, Clone)]
#[table(classes_provider = "TailwindClassesPreset")]
pub struct Book {
id: u32,
title: String,
}
字段获取器
有时您想显示的不是结构体的一部分,而是来自其他字段或完全不同的派生值。为此,您可以使用 FieldGetter 类型或 getter 属性。
让我们从 FieldGetter 开始,并查看一个示例
#[derive(TableRow, Clone)]
#[table(classes_provider = "TailwindClassesPreset")]
pub struct Book {
id: u32,
title: String,
author: String,
// this tells the macro that you're going to provide a method called `title_and_author` that returns a `String`
title_and_author: FieldGetter<String>
}
impl Book {
// Returns the value that is displayed in the column
pub fn title_and_author(&self) -> String {
format!("{} by {}", self.title, self.author)
}
}
为了提供最大的灵活性,您可以使用 getter 属性。
#[derive(TableRow, Clone)]
#[table(classes_provider = "TailwindClassesPreset")]
pub struct Book {
// this tells the macro that you're going to provide a method called `get_title` that returns a `String`
#[table(getter = "get_title")]
title: String,
}
impl Book {
pub fn get_title(&self) -> String {
format!("Title: {}", self.title)
}
}
何时使用 FieldGetter 与 getter 属性
类型为 FieldGetter<T> 的字段是一个虚拟字段,实际上在结构体上并不存在。内部上,FieldGetter 只是一个重新类型化的 PhantomData,因此在编译时被移除。因此,它不会增加内存使用。这意味着您应该仅用于纯派生数据。
应将 getter 属性用于结构体上实际存在的字段,但您希望在其渲染之前修改其值。
自定义渲染器
可以使用自定义渲染器来自定义表格的几乎所有方面。它们通过在 TableContent 组件的结构体或字段或属性上使用各种 ...renderer 属性来指定。要实现自定义渲染器,请查看以下默认渲染器。
在结构体级别上,您可以使用此属性
thead_cell_renderer- 默认为DefaultTableHeaderCellRenderer,它渲染<th><span>Title</span></th>以及排序功能(如果启用)。
作为 `TableContent` 组件的属性,你可以使用以下功能
thead_renderer- 默认为DefaultTableHeadRenderer,它仅渲染 `thead` 标签。thead_row_renderer- 默认为DefaultTableHeadRowRenderer,它仅渲染 `tr` 标签。tbody_renderer- 默认为 `tbody` 标签。不接收任何属性。row_renderer- 默认为DefaultTableRowRenderer。loading_row_renderer- 默认为DefaultLoadingRowRenderer。error_row_renderer- 默认为DefaultErrorRowRenderer。row_placeholder_renderer- 默认为DefaultRowPlaceholderRenderer。
在字段级别上,你可以使用 renderer 属性。
它默认为 DefaultTableCellRenderer。适用于实现了标准库类型、流行crate的feature标志以及你自定义类型(如果你为它们实现了此trait)的任何实现了 CellValue 特性的类型。
示例
#[derive(TableRow, Clone)]
pub struct Book {
title: String,
#[table(renderer = "ImageTableCellRenderer")]
img: String,
}
// Easy cell renderer that just displays an image from an URL.
#[component]
fn ImageTableCellRenderer<F>(
class: String,
#[prop(into)] value: MaybeSignal<String>,
on_change: F,
index: usize,
) -> impl IntoView
where
F: Fn(String) + 'static,
{
view! {
<td class=class>
<img src=value alt="Book image" height="64"/>
</td>
}
}
有关更详细的信息,请参阅 custom_renderers_svg 示例 以实现完全自定义。
可编辑单元格
你可能已经注意到了上面自定义单元格渲染器中的类型参数 F。这可以用于在单元格更改时发出事件。在最简单的情况下,你可以使用一个使用 `<input>` 的单元格渲染器。
#[derive(TableRow, Clone, Default, Debug)]
#[table(impl_vec_data_provider)]
pub struct Book {
id: u32,
#[table(renderer = "InputCellRenderer")]
title: String,
}
// Easy input cell renderer that emits `on_change` when the input is changed.
#[component]
fn InputCellRenderer<F>(
class: String,
#[prop(into)] value: MaybeSignal<String>,
on_change: F,
index: usize,
) -> impl IntoView
where
F: Fn(String) + 'static,
{
view! {
<td class=class>
<input type="text" value=value on:change=move |evt| { on_change(event_target_value(&evt)); } />
</td>
}
}
// Then in the table component you can listen to the `on_change` event:
#[component]
pub fn App() -> impl IntoView {
let rows = vec![Book::default(), Book::default()];
let on_change = move |evt: ChangeEvent<Book>| {
logging::log!("Changed row at index {}:\n{:#?}", evt.row_index, evt.changed_row);
};
view! {
<table>
<TableContent rows on_change />
</table>
}
}
请参阅 editable 示例 以获取完整的示例。
分页 / 虚拟化 / 无限滚动
此表格组件支持不同的显示加速策略。你可以通过 `TableContent` 组件的 `display_strategy` 属性来设置它们。
以下选项可用。请查看它们的文档以获取更多详细信息。
请查看分页示例以获取有关如何使用分页的更多信息。
国际化(I18n)
要使用leptos-i18n翻译表格的列标题,您可以启用"i18n"功能。结构体的字段名称用作键。
请查看i18n 示例。
贡献
欢迎所有贡献。如果您有任何想法或问题,请提交问题或拉取请求。
Leptos 兼容性
| 包版本 | 兼容的 Leptos 版本 |
|---|---|
| <= 0.2 | 0.3 |
| 0.3 | 0.4 |
| 0.4, 0.5, 0.6 | 0.5 |
| 0.7 – 0.12 | 0.6 |
依赖项
~22–35MB
~569K SLoC