跳到主要内容
版本:Next

深入了解 Widget

在 Ribir 中:

  • 视图由 widget 作为基本单位构建。
  • widget 之间通过纯组合的方式组成新的 widget。

Ribir 的独特之处在于它是通过纯组合的方式来组成新的 widget。

纯组合

当我们说纯组合时,意味着: widget 之间的父子关系并不涉及所有权,父 widget 通过 trait 来约定可以有子 widget,但并不拥有子 widget。

通常,其它框架的数据结构是这样的,父亲通过一个类似 children 的属性持有孩子:

struct Parent {
property: &'static str,
children: Vec<Child>,
}

struct Child {
property: &'static str,
}

let widget = Parent {
property: "parent",
children: vec![
Child { property: "child1" },
Child { property: "child2" },
],
};

而在 Ribir 中,数据结构却是类似这样的:

struct Parent {
property: &'static str,
}

struct Child {
property: &'static str,
}

let parent = Parent { property: "parent" };
let child1 = Child { property: "child1" };
let child2 = Child { property: "child2" };

let widget = MultiPair {
parent,
children: vec![child1, child2],
};

父 widget 和子 widget 之间是完全透明和独立的,我们并不将子 widget 添加到父 widget 中。

当然,这只是一个简化的例子。实际上,Ribir 的组合方式更加灵活,而且在实际使用中,你不会接触到 MultiPair 这样的中间数据结构。

这种组合方式的优点是,它产生的 widget 更小,更纯粹,更容易复用,可以根据需要进行组合。让我们以 Ribir 的内建 widget 为例来说明这一点。

在传统的 GUI 框架中,我们通常通过继承一个基础对象(或类似的方式)来获得一组常用的基础功能。这个基础对象通常包含许多属性,因此并不小。然而,在 Ribir 中,我们通过按需组合一组迷你的内建 widget 来实现这些功能。以 Opacity 为例,在 Ribir 中,它只有一个 f32 类型的属性。当你需要改变 widget 的透明度时,你可以直接使用 Opacity 来组合你的 widget:

use ribir::prelude::*;

// Opacity 的定义是这样的:
// struct Opacity { opacity: f64 }

let w = Opacity { opacity: 0.5 }.with_child(Void, ctx);

当然,实际代码中,你可以直接写成 @Void { opacity: 0.5 }

四种基础 widget

即将推出

  • render widget
  • compose widget
  • compose child widget
  • function widget