0

如何将input事件侦听器添加到HtmlInputElement/ HtmlTextAreaElement。我正在使用web-sys并阅读this,但是在此之后,我在闭包内使用的所有元素(在这种情况下尤其是input元素)都被移动到闭包中,之后我无法附加侦听器。

let closure = Closure::wrap(Box::new(|_: web_sys::InputEvent| {
    console_log!("{}", input.value());
}) as Box<dyn FnMut(_)>);

input.add_event_listener_with_callback("input", closure.as_ref().unchecked_ref())?;
// ^
// Doesn't work because the `input` variable was moved into the closure.

具体来说,我得到:

borrow of moved value: `input`
4

2 回答 2

1

它现在可以编译,虽然我无法测试它是否真的有效。我改变了什么:

  1. 用于Rc<RefCell<INPUT>>避免有关已移动变量的错误

  2. 用于Rc::downgrade(&input)提供Weak内部闭包以避免循环引用,从而避免内存泄漏。但我不确定整个事情在 web env 中是如何工作的,所以也许 a 它应该是Rc,因为Rc将在方法结束时删除run()

你应该查看相关的 rustdoc 以获得关于这些类型在做什么的更详细的解释。

use wasm_bindgen::{prelude::*, JsCast};
use web_sys::HtmlElement;
use std::cell::RefCell;
use std::rc::Rc;

#[wasm_bindgen]
pub fn run(cont: &HtmlElement) -> Result<(), JsValue> {
    let window = web_sys::window().expect("could not get window handle");
    let document = window.document().expect("could not get document handle");
    let input = document
        .create_element("textarea")?
        .dyn_into::<web_sys::HtmlTextAreaElement>()?;

    let input = Rc::new(RefCell::new(input));
    let weak_input = Rc::downgrade(&input);

    let closure: Box<dyn FnMut(_)> = Box::new(move |_: web_sys::InputEvent| {
        let input = weak_input.upgrade().unwrap();
        let _a = &input.borrow().value();
    });

    let closure = Closure::wrap(closure);

    input
        .borrow_mut()
        .add_event_listener_with_callback("input", closure.as_ref().unchecked_ref())?;
    closure.forget();

    cont.append_child(&input.borrow())?;

    Ok(())
}

于 2021-08-26T19:36:47.617 回答
0

首先,我要感谢Svetlin Zarev抽出时间回答我的问题。没有他们,我不会走到这一步。请查看他们的答案

对于来自 javascript 的人来说,所有这些东西都是相当多的,我想提出一个“简单”的答案。

要添加input(或实际上任何类型的)事件侦听器并捕获目标值,您可以使用以下代码:

let cb = Closure::wrap(Box::new(|e: Event| {
    let input = e
        .current_target()
        .unwrap()
        .dyn_into::<web_sys::HtmlTextAreaElement>()
        .unwrap();

    console_log!("{:?}", input.value());
}) as Box<dyn FnMut(_)>);

input.add_event_listener_with_callback("input", &cb.as_ref().unchecked_ref())?;

cb.forget();

我还建议阅读以下文章:

于 2021-08-27T19:12:19.713 回答