24 个版本 (10 个破坏性更新)
新增 0.11.1 | 2024年8月5日 |
---|---|
0.11.0 | 2024年5月26日 |
0.10.0 | 2024年2月22日 |
0.8.1 | 2023年11月2日 |
0.5.0 |
|
#1308 in 过程宏
每月272次 下载
用于 leptos-struct-table
21KB
514 行
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
属性。内部实现为 Vec<T>
实现了 TableDataProvider
特性。
要利用具有缓存功能的异步部分数据加载的完整功能,您应该实现特性 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
- 快速自定义单元格格式化方式,无需创建自定义渲染器。有关更多信息,请参阅下方的 格式化。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
。适用于实现了CellValue
特质的任何类型,包括标准库中的类型、带有功能标志的流行crate以及如果您为它们实现了此特质,则适用于您的自定义类型。
示例
#[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
。这可以用于在单元格更改时发出事件。在 simplest 情况下,您可以使用使用<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
属性来设置它们。
以下选项可用。请查看它们的文档以获取更多详细信息。
有关如何使用分页的更多信息,请参阅pagination示例。
贡献
欢迎所有贡献。如果您有任何想法或问题,请打开一个问题或发送一个pull request。
Leptos 兼容性
crate 版本 | 兼容的 Leptos 版本 |
---|---|
<= 0.2 | 0.3 |
0.3 | 0.4 |
0.4, 0.5, 0.6 | 0.5 |
0.7, 0.8, 0.9, 0.10 | 0.6 |
依赖项
~0.7–1.2MB
~26K SLoC