如何将yew::Callback<MouseEvent>转换为FnMut(MouseEvent)?
问题解决方案
问题核心在于你捕获了props中Callback的引用,导致闭包生命周期被限制为函数的临时生命周期,而核心库要求'static的闭包。以下是具体解决步骤和修改后的代码:
修改思路
- 克隆props中的
Callback,得到拥有所有权的实例(Yew的Callback内部通过Rc管理,本身是'static生命周期)。 - 在闭包里使用这个拥有所有权的
Callback,让闭包满足'static要求。 - 移除不必要的闭包克隆操作,直接将闭包装箱传递给核心库。
修改后的组件代码
/// this is my core library use core::components::buttons::elevated::{self, ElevatedButtonData, ElevatedButtonOpts}; use web_sys::{HtmlElement, MouseEvent}; use yew::{function_component, virtual_dom::VNode, AttrValue, Callback, Html, Properties}; #[derive(PartialEq, Properties)] pub struct ElevatedButtonProps { pub label: AttrValue, #[prop_or(false)] pub disable: bool, #[prop_or_default] pub icon: Option<AttrValue>, #[prop_or_default] pub onclick: Option<Callback<MouseEvent>>, } #[function_component(ElevatedButton)] pub fn elevated_button(props: &ElevatedButtonProps) -> Html { let ElevatedButtonProps { label, disable, icon, onclick, } = props; let icon = icon.as_ref().map(|i| i.to_string()); let inner = match onclick { Some(onclick_ref) => { // 克隆得到拥有所有权的Callback,满足'static生命周期 let onclick = onclick_ref.clone(); // 闭包捕获拥有所有权的Callback,无需依赖props的临时生命周期 let cb = move |e: MouseEvent| { onclick.emit(e); }; ElevatedButtonData { label: label.to_string(), icon, onclick: Some(Box::new(cb)), } } None => ElevatedButtonData { label: label.to_string(), icon, onclick: None, }, }; let opts = ElevatedButtonOpts { disable: *disable }; let button: HtmlElement = elevated::ElevatedButton::new(inner, opts); VNode::VRef(button.into()) }
补充说明
- Yew的
Callback天生具备'static生命周期,克隆后的实例完全独立,不受原props的生命周期限制。 - 闭包捕获拥有所有权的
Callback后,自身自动满足'static要求,可直接装箱传递给核心库。 - 由于
Callback::emit是&self方法,闭包实际属于Fn类型,而Fn是FnMut的子trait,编译器会自动完成类型转换,无需额外处理。
内容的提问来源于stack exchange,提问作者al3x
相关产品推荐
相关产品推荐

