Druid应用程序的核心是应用程序模型。模型驱动 UI。当您更改模型时,Druid 会比较旧版本和新版本,并将更改传播到受更改影响的应用程序组件(“ widgets”)。
为此,您的模型必须实现 Clone 和 Data 特性。您的模型克隆成本低是很重要的; 我们鼓励使用引用计数指针来允许克隆成本更高的类型。Arc 和 Rc 具有覆盖数据隐含,所以如果您有一个不实现 Data 的类型,那么您总是可以将它包装在其中一个智能指针中。
Trait druid::Data (派生宏)
#[derive(Clone, Data)]
enum Foo {
Case1(i32, f32),
Case2 { a: String, b: Arc<i32> }
}
有许多字段属性可用于派生(数据)。
#[data(ignore)]
计算相同性时跳过此字段。
如果实现 Data 的类型包含一些与 Data impl 无关的字段,则可以使用此属性忽略它们。
#[data(same_fn = "path")]
使用特定的函数来计算相同性。
默认情况下,Data 的派生实现只在每个字段上递归地调用 Data: : 。使用此属性,您可以指定将改为使用的自定义函数。
这个函数必须在表单 fn < T > (& T,& T)-> bool 中有一个签名,其中 T 是字段的类型。
集合类型
没有为标准的集合类型实现Data,因为他们比较消耗,如果在Druid中使用集合类型,有两种简单的选择: 要么将集合包装在一个 Arc 中或者构建具有 IM 特性的Druid,该特性将Data实现添加到收集箱中,一组不可变的数据结构,非常适合Druid
如果使用 IM 特性,则从Druid板条箱的根重新导出板条箱。
#[derive(Clone, Data)]
struct PathEntry {
// PathBuf 没有实现Data,但是没有问题
#[data(same_fn = "PartialEq::eq")]
path: PathBuf,
priority: usize,
// 该字段不属于我们的数据模型。
#[data(ignore)]
last_read: Instant,
}
C-style enum
对于“ c 样式”枚举(只包含单位变量的枚举,即没有变量具有字段) ,生成的实现检查是否相等。因此,这些类型还必须实现 PartialEq。
方法
pub fn same(&self, other: &Self) -> bool
确认两个值是否相同
这是为了始终是一个快速的操作。如果返回 true,则这两个值必须相等,但两个相等的值在这里不必被认为是相同的,因为在分配两个副本时通常会出现这种情况。
请注意,上面的“等于”与 PartialEq 的含义略有不同,例如,当两个浮点 NaN 值具有相同的位表示形式时,它们应该被认为是相等的。
例子
use druid::Data;
use std::sync::Arc;
#[derive(Clone, Data)]
/// 待办事项列表应用程序的主模型。
struct TodoList {
items: Arc<Vec<TodoItem>>,
}
#[derive(Clone, Data)]
///一个待办事项
struct TodoItem {
category: Category,
title: String,
note: Option<String>,
completed: bool,
// 这里DateTime没有实现Data,所以使用Arc
due_date: Option<Arc<DateTime>>,
// 你可以自定义比较的fn
#[data(same_fn = "PartialEq::eq")]
added_date: DateTime,
//你也可以指定字段在比较时跳过
#[data(ignore)]
debug_timestamp: usize,
}
#[derive(Clone, Data, PartialEq)]
/// 三种任务类型
enum Category {
Work,
Play,
Revolution,
}