如何在Yew Callback中修改变量以更新输入标签?
在Yew中使用Callback更新输入框标签
我想基于Yew文档的最后一个示例,用Callback更新输入框的标签(而非仅输出控制台日志),也就是修改闭包外的字符串并用于后续HTML渲染,但当前代码报错:
#[function_component(Settings)] pub fn settings_page() -> Html { let mut value_label = String::new(); let onchange_slider = { Callback::from(move |e: Event| { let input: HtmlInputElement = e.target_unchecked_into(); let value = input.value().parse::<i32>().unwrap_or(10); log::info!("value = {}", value); // 这部分正常工作 value_label = format!("The value is {}", value); // 错误:闭包因修改变量value_label而成为FnMut }) }; html! { <div class="slider"> <input type="range" class="form-range" min="-5" max="20" id="my_broken_slider" onchange={onchange_slider.clone()} /> <label for="my_broken_slider" class="form-label">{value_label}</label> </div> } }
问题核心:Yew的Callback是包裹在Rc中的Fn类型,要求闭包不可变;同时普通字符串变量的修改不会触发组件重渲染,就算编译通过,UI也不会更新。
解决方案:用use_state管理响应式状态
Yew函数组件必须通过状态钩子管理需要更新的变量,use_state会创建带setter的响应式状态,既适配Callback的要求,又能触发组件重渲染:
use yew::prelude::*; #[function_component(Settings)] pub fn settings_page() -> Html { // 初始化响应式状态,初始值为空字符串 let value_label = use_state(|| String::new()); let onchange_slider = { // 克隆状态句柄,供闭包捕获(Rc克隆成本极低) let value_label = value_label.clone(); Callback::from(move |e: Event| { let input: HtmlInputElement = e.target_unchecked_into(); let value = input.value().parse::<i32>().unwrap_or(10); log::info!("value = {}", value); // 调用setter更新状态,自动触发组件重渲染 value_label.set(format!("The value is {}", value)); }) }; html! { <div class="slider"> <input type="range" class="form-range" min="-5" max="20" id="my_slider" onchange={onchange_slider} /> <label for="my_slider" class="form-label">{value_label}</label> </div> } }
关键说明:
use_state返回的UseStateHandle<String>是包裹Rc的引用类型,克隆操作廉价,完全符合Callback对Fn的要求。- 调用
set()方法更新状态时,Yew会自动检测变化并重新渲染组件,确保标签文本实时更新。 - HTML中直接写
{value_label}即可,Yew的Html宏会自动处理UseStateHandle的Deref特性,无需手动解引用。
内容的提问来源于stack exchange,提问作者djmcmath
相关产品推荐
相关产品推荐

