From fee5b7ba94cff8fbdd687a58129e637c0de1c385 Mon Sep 17 00:00:00 2001 From: xfy Date: Thu, 2 Jul 2026 17:15:18 +0800 Subject: [PATCH] =?UTF-8?q?refactor(wasm):=20=E6=B6=88=E9=99=A4=20DOM=20?= =?UTF-8?q?=E4=BA=92=E6=93=8D=E4=BD=9C=E4=B8=AD=E7=9A=84=20js=5Fsys::eval?= =?UTF-8?q?=20=E5=AD=97=E7=AC=A6=E4=B8=B2=E6=B1=82=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 对照 Dioxus "Breaking Out" 文档审查后,将 3 处 js_sys::eval 改为 类型化调用,与 tiptap_bridge/codemirror_bridge 风格统一: - utils/time.rs sleep_ms:eval("new Promise(r=>setTimeout(r,n))") 改为 js_sys::Promise + web_sys::Window::set_timeout_*,复用项目内 system.rs::wasm_sleep 同款写法。 - theme.rs 主题切换:format!-into-eval 拼 __startThemeTransition(x,y) 改为 Reflect::get 取函数 + Function::call2,消除字符串注入面 (原坐标虽为 f64 无实际风险,但属不必要 eval)。 - post_content.rs:__initPostContent / __initLightbox 两处 eval 字面量 改为 invoke_optional_global 辅助函数(Reflect::get + Function::apply), 消除旧版 "eval 字符串粘贴" 模式;__lightboxSelectors 直接复用 JsValue 传入,省去一次回读。 --- src/components/post/post_content.rs | 40 ++++++++++++++++++++++++----- src/theme.rs | 22 ++++++++-------- src/utils/time.rs | 20 ++++++++++----- 3 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/components/post/post_content.rs b/src/components/post/post_content.rs index 1ae213c..1dd1aad 100644 --- a/src/components/post/post_content.rs +++ b/src/components/post/post_content.rs @@ -4,6 +4,27 @@ use dioxus::prelude::*; +/// 读取 `window` 上的可选全局函数并调用;函数未定义/为 null 时静默跳过。 +/// +/// 替代 `js_sys::eval("if(window.__x) window.__x(...)")` 字符串拼贴模式:用 +/// `Reflect::get` 取属性 + `Function::apply` 调用,无字符串求值,与 `tiptap_bridge` +/// 的类型化 extern 风格一致。 +#[cfg(target_arch = "wasm32")] +fn invoke_optional_global(window: &web_sys::Window, name: &str, args: &[wasm_bindgen::JsValue]) { + use wasm_bindgen::JsCast; + if let Ok(fn_val) = js_sys::Reflect::get(window, &name.into()) { + if !fn_val.is_undefined() && !fn_val.is_null() { + let arr = js_sys::Array::new(); + for a in args { + arr.push(a); + } + let _ = fn_val + .unchecked_into::() + .apply(window, &arr); + } + } +} + /// 文章内容组件。 /// /// Props: @@ -18,14 +39,21 @@ use dioxus::prelude::*; pub fn PostContent(content_html: String) -> Element { #[cfg(target_arch = "wasm32")] use_effect(move || { - let _ = js_sys::eval("window.__initPostContent('.post-content')"); + let window = web_sys::window().unwrap(); + + // 调用 window.__initPostContent('.post-content'):函数不存在时静默跳过 + // (与旧 eval 中的 if 守卫语义一致)。 + invoke_optional_global(&window, "__initPostContent", &[".post-content".into()]); + // lightbox 改由 Dioxus.toml 全局