2022抛弃js ,拥抱Rust,Yew框架(四) - 函数式组件

931 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

Function Components

函数组件是常规组件的简化版,主要由一个函数组成,还函数接收Props,并返回的HTMl.基本相当于view方法,只能创建纯组件.产生了hooks,Hooks 允许函数组件维护自己的内部状态并使用其他 Yew 功能,而无需手动实现Component trait#[function_component] 属性宏,会自动实现FunctionProvider,对外暴露

use yew::{function_component, html};

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

Hooks

钩子是让你“钩住”组件的状态 和/或 生命周期并执行操作的函数。yew有几个预定义的钩子。你也可以创建自己的。

use_state

use_state用于管理函数组件中的状态。它返回一个UseStateHandle对象,该对象Deref为当前值,并提供set方法去更新这个值。

钩子将一个函数作为输入,该函数确定初始状态。该值在后续渲染中保持最新。

setter 函数保证在整个组件生命周期中是相同的。如果您只打算从挂钩中设置值,则可以安全地UseStateHandle从依赖项中省略。use_effect_with_deps

这个钩子总是会在接收到新状态时触发重新渲染。查看 use_state_eq您是否希望组件仅在状态更改时重新渲染。

use yew::{Callback, function_component, html, use_state};

#[function_component(UseState)]
fn state() -> Html {
    let counter = use_state(|| 0);
    let onclick = {
        let counter = counter.clone();
        Callback::from(move |_| counter.set(*counter + 1))
    };


    html! {
        <div>
            <button {onclick}>{ "Increment value" }</button>
            <p>
                <b>{ "Current value: " }</b>
                { *counter }
            </p>
        </div>
    }
}

use_state_eq

与use_state有相同的效果,但是只有当setter接收到prev_state=next_state时触发。

tip:这个钩子需要state对象来实现PartialEq。

use_ref

use_ref用于获取对值的不可变引用。它的状态在不同的渲染中持续存在。 use_ref可用保持状态在组件生命周期内,不能克隆存储在组件寿命更长的Rc任何地方. 如果需要一个可变引用,请考虑使用se_mut_ref。如果需要在状态更改上重新呈现组件,请考虑使用use_state。

// EventBus is an implementation of yew_agent::Agent
use website_test::agents::EventBus;
use yew::{function_component, html, use_ref, use_state, Callback};
use yew_agent::Bridged;

#[function_component(UseRef)]
fn ref_hook() -> Html {
    let greeting = use_state(|| "No one has greeted me yet!".to_owned());

    {
        let greeting = greeting.clone();
        use_ref(|| EventBus::bridge(Callback::from(move |msg| {
            greeting.set(msg);
        })));
    }

    html! {
        <div>
            <span>{ (*greeting).clone() }</span>
        </div>
    }
}

use_mut_ref

use_mut_ref用于获取对值的可变引用。它的状态在不同的渲染中持续存在。

需要注意的是,状态更改不会通知您。如果需要在状态更改上重新呈现组件,use_state。

use web_sys::HtmlInputElement;
use yew::{
    events::Event,
    function_component, html, use_mut_ref, use_state,
    Callback, TargetCast,
};

#[function_component(UseMutRef)]
fn mut_ref_hook() -> Html {
    let message = use_state(|| "".to_string());
    let message_count = use_mut_ref(|| 0);

    let onclick = Callback::from(move |_| {
        let window = gloo_utils::window();

        if *message_count.borrow_mut() > 3 {
            window.alert_with_message("Message limit reached").unwrap();
        } else {
            *message_count.borrow_mut() += 1;
            window.alert_with_message("Message sent").unwrap();
        }
    });

    let onchange = {
        let message = message.clone();
        Callback::from(move |e: Event| {
            let input: HtmlInputElement = e.target_unchecked_into();
            message.set(input.value());
        })
    };

    html! {
        <div>
            <input {onchange} value={(*message).clone()} />
            <button {onclick}>{ "Send" }</button>
        </div>
    }
}