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