You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将yew::Callback<MouseEvent>转换为FnMut(MouseEvent)?

问题解决方案

问题核心在于你捕获了props中Callback的引用,导致闭包生命周期被限制为函数的临时生命周期,而核心库要求'static的闭包。以下是具体解决步骤和修改后的代码:

修改思路

  1. 克隆props中的Callback,得到拥有所有权的实例(Yew的Callback内部通过Rc管理,本身是'static生命周期)。
  2. 在闭包里使用这个拥有所有权的Callback,让闭包满足'static要求。
  3. 移除不必要的闭包克隆操作,直接将闭包装箱传递给核心库。

修改后的组件代码

/// 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 02:12:25