Yew框架中函数组件的属性(Props)机制详解

Yew框架中函数组件的属性(Props)机制详解

yew Rust / Wasm framework for creating reliable and efficient web applications yew 项目地址: https://gitcode.com/gh_mirrors/ye/yew

前言

在Yew框架中,属性(Properties,简称Props)是组件间通信的重要机制,特别是父组件向子组件传递数据的方式。本文将深入剖析Yew中函数组件的属性系统,帮助开发者更好地理解和使用这一核心特性。

属性基础概念

属性本质上就是组件的参数,Yew框架能够监控这些属性的变化。在Yew中,任何类型要作为组件属性使用,都必须实现Properties trait。

响应式特性

Yew在重新渲染时会在虚拟DOM协调过程中检查属性是否发生变化,以确定是否需要重新渲染嵌套组件。这种机制使得Yew成为一个高度响应式的框架:

  • 父组件的变更总是会向下传播
  • 视图永远不会与来自属性/状态的数据不同步

属性实现方式

派生宏

Yew提供了派生宏来简化Properties trait的实现。需要注意的是,派生Properties的类型必须同时实现PartialEq,以便Yew能够进行数据比较。

use yew::Properties;

#[derive(Properties, PartialEq)]
pub struct Props {
    pub is_loading: bool,
}

在函数组件中使用属性

#[function_component]属性允许函数组件可选地接收属性参数。在html!宏中通过属性赋值来传递这些参数。

带属性的组件示例

use yew::{function_component, html, Html, Properties};

#[derive(Properties, PartialEq)]
pub struct Props {
    pub is_loading: bool,
}

#[function_component]
fn HelloWorld(&Props { is_loading }: &Props) -> Html {
    html! { <>{"Am I loading? - "}{is_loading}</> }
}

#[function_component]
fn App() -> Html {
    html! { <HelloWorld is_loading=true /> }
}

不带属性的组件示例

use yew::{function_component, html, Html};

#[function_component]
fn HelloWorld() -> Html {
    html! { "Hello world" }
}

#[function_component]
fn App() -> Html {
    html! { <HelloWorld /> }
}

属性字段的派生宏属性

在派生Properties时,默认所有字段都是必需的。以下属性允许你为属性设置默认值,当父组件没有提供这些值时使用。

1. #[prop_or_default]

使用字段类型的Default trait的默认值初始化属性值。

#[derive(Properties, PartialEq)]
pub struct Props {
    #[prop_or_default]
    pub is_loading: bool,
}

2. #[prop_or(value)]

使用指定的value初始化属性值。value可以是返回字段类型的任何表达式。

#[derive(Properties, PartialEq)]
pub struct Props {
    #[prop_or(AttrValue::Static("Bob"))]
    pub name: AttrValue,
}

3. #[prop_or_else(function)]

调用指定的function来初始化属性值。函数签名应为FnMut() -> T,其中T是字段类型。

fn create_default_name() -> AttrValue {
    AttrValue::Static("Bob")
}

#[derive(Properties, PartialEq)]
pub struct Props {
    #[prop_or_else(create_default_name)]
    pub name: AttrValue,
}

属性的内存/性能考虑

Yew内部使用引用计数来处理属性,这意味着在组件树中传递的只是属性的共享指针。这种设计避免了克隆整个属性可能带来的性能开销。

重要提示:建议使用AttrValue作为属性值的类型,而不是直接使用String等类型,这样可以获得更好的性能。

Props宏的使用

yew::props!宏允许你以类似于html!宏的方式构建属性。它使用与结构体表达式相同的语法。

let pre_made_props = yew::props! {
    Props {} // 注意我们不需要指定name属性
};
html! { <Hello ..pre_made_props /> }

自动生成属性(yew-autoprops)

为了简化开发流程,可以使用#[autoprops]宏(来自yew-autoprops crate)自动生成Properties结构体。

use yew_autoprops::autoprops;

#[autoprops]
#[function_component]
fn Greetings(
    #[prop_or_default]
    is_loading: bool,
    #[prop_or(AttrValue::Static("Hello"))]
    message: &AttrValue,
) -> Html {
    if is_loading {
        html! { "Loading" }
    } else {
        html! { <>{message}</> }
    }
}

属性评估顺序

属性按照它们在结构体中声明的顺序进行评估:

let mut g = 1..=3;
let props = yew::props!(Props { 
    first: g.next().unwrap(), 
    second: g.next().unwrap(), 
    last: g.next().unwrap() 
});

应避免的反模式

在使用属性时,应避免以下反模式:

  1. 使用String而非AttrValueString克隆成本高,而AttrValue是引用计数字符串,克隆成本低。
  2. 使用内部可变性:如RefCellMutex等,可能导致重新渲染问题。
  3. 使用Vec而非IArrayVec克隆成本高,而IArray是引用计数切片,克隆成本低。

总结

Yew框架的属性系统提供了灵活而强大的组件间通信机制。通过合理使用默认值、引用计数类型和自动生成工具,可以构建出既高效又易于维护的组件结构。理解属性的工作原理和最佳实践,将有助于开发出性能更优的Yew应用。

yew Rust / Wasm framework for creating reliable and efficient web applications yew 项目地址: https://gitcode.com/gh_mirrors/ye/yew

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宣聪麟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值