如何用 yew 查询和更新 DOM?

发布于 2025-01-18 03:17:26 字数 1021 浏览 5 评论 0原文

有没有办法通过 use_node_ref 进行 DOM 操作?或者,如何使用 yew 在 Rust 中执行 document.query_selector()

use web_sys::HtmlInputElement;
use yew::{
    function_component, functional::*, html,
    NodeRef, Html
};

#[function_component(UseRef)]
pub fn ref_hook() -> Html {
    let input_ref = use_node_ref();
    let all_editables =  input_ref.query_selector("[contenteditable]")
    web_sys::console::(all_editables)

    html! {
        <div>
            <input ref={input_ref} type="number" />
        </div>
    }
}

目标:我有一个富文本编辑器应用程序。我有一个像这样的字符串形式的缩小的 html

;这是标题

hello world,我需要获取 DOM 并更改 innerHTML 以将其设置为此值。

目标2:当用户在contenteditable元素中写入内容时,我还需要更新innerHtml。例如,当用户输入 @john smith 时,我将使用 href 创建一个 元素,其中包含指向 的链接>约翰·史密斯的个人资料。

Is there any way to make DOM action via use_node_ref? or alternatively, how to do document.query_selector() in Rust using yew?

use web_sys::HtmlInputElement;
use yew::{
    function_component, functional::*, html,
    NodeRef, Html
};

#[function_component(UseRef)]
pub fn ref_hook() -> Html {
    let input_ref = use_node_ref();
    let all_editables =  input_ref.query_selector("[contenteditable]")
    web_sys::console::(all_editables)

    html! {
        <div>
            <input ref={input_ref} type="number" />
        </div>
    }
}

Goal: I have a rich text editor app. And I have a minified html in form of string like this <h1> this is title</h1><p>hello world</> and I need to get the DOM and change the innerHTML to set it to this value.

Goal2: I will also need to update the innerHtml as the user write things in the contenteditable elements. Fore example when the user type @john smith I will make a create an <a> element with href the have the link to John smith's profile.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

莫多说 2025-01-25 03:17:26

你的问题有很多事情需要解决。

#1 不要设置内部 html

更多内容请阅读 innerHTML 的替代方案?

,而是创建文本节点。
因此,使用 web-sys 你会做类似的事情:

let txtNode: Node = window()
    .unwrap_throw()
    .document()
    .unwrap_throw()
    .create_text_node("Hello")
    .dyn_into()
    .unwrap_throw();

myDomElement.append_hild(&txtNode).unwrap_throw();

#2 如何从输入查询数据

有很多方法可以做到这一点,所以我只向你展示其中一种 -
受控输入的

核心思想是将输入值保留在 use_state 中,并使用 valueoninput 属性将其与输入元素同步。

#[function_component(ControlledInputComponent)]
pub fn controlled_input_component() -> Html {
    let my_text_handle = use_state(|| "".to_string());
    let my_text = (*my_text_handle).clone();
    
    let handle_input = Callback::from(move |input_event: InputEvent| {
        let event: Event = input_event.dyn_into().unwrap_throw();
        let input_elem: HTMLInputElement = event.target().unwrap_throw().dyn_into().unwrap_throw();
        let value = input_elem.value();
        my_text_handle.set(value); // update as user types
        
    });

    html! {
        <div>
            <input type="text" value={my_text} oninput={handle_input} />
        </div>
    }
}

#3 更新 DOM

**在 yew 外部,因为您通常应该避免更新由 yew 控制的 DOM

然后您可以使用 use_effec_with_deps 对您的输入更改做出反应并在那里更新您的外部预览

let my_text_handle = use_state(|| "".to_string());
let my_text = (*my_text_handle).clone();

use_effect_with_deps(move |my_text| {
    // run all the code from my tip #1 like:
    // myDomElement.append_hild(&txtNode).unwrap_throw();
    ||{}
}, my_text);

Many things to tackle with your question.

#1 Do not set inner html

More to read about this in Alternative for innerHTML?

But instead create text nodes.
So using web-sys you would do something like:

let txtNode: Node = window()
    .unwrap_throw()
    .document()
    .unwrap_throw()
    .create_text_node("Hello")
    .dyn_into()
    .unwrap_throw();

myDomElement.append_hild(&txtNode).unwrap_throw();

#2 How to query data from an input

There are many ways to do this so ill just show you one of them -
controlled input

core idea is keep your input value in use_state and sync it with the input element using value and oninput attributes.

#[function_component(ControlledInputComponent)]
pub fn controlled_input_component() -> Html {
    let my_text_handle = use_state(|| "".to_string());
    let my_text = (*my_text_handle).clone();
    
    let handle_input = Callback::from(move |input_event: InputEvent| {
        let event: Event = input_event.dyn_into().unwrap_throw();
        let input_elem: HTMLInputElement = event.target().unwrap_throw().dyn_into().unwrap_throw();
        let value = input_elem.value();
        my_text_handle.set(value); // update as user types
        
    });

    html! {
        <div>
            <input type="text" value={my_text} oninput={handle_input} />
        </div>
    }
}

#3 Update DOM

**External to yew as you should generally avoid updating DOM that is controlled by yew

You can then use use_effec_with_deps to react to your input changing and update your external preview there

let my_text_handle = use_state(|| "".to_string());
let my_text = (*my_text_handle).clone();

use_effect_with_deps(move |my_text| {
    // run all the code from my tip #1 like:
    // myDomElement.append_hild(&txtNode).unwrap_throw();
    ||{}
}, my_text);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文