一起养成写作习惯!这是我参与「掘金日新计划 · 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>
}
}