Pārlūkot izejas kodu

fix: component pass thru events

Jonathan Kelley 3 gadi atpakaļ
vecāks
revīzija
c439b0ac7e

+ 8 - 8
examples/framework_benchmark.rs

@@ -41,22 +41,22 @@ fn app(cx: Scope) -> Element {
                     div { class: "col-md-6",
                         div { class: "row",
                             ActionButton { name: "Create 1,000 rows", id: "run",
-                                onclick: move || items.set(Label::new_list(1_000)),
+                                onclick: move |_| items.set(Label::new_list(1_000)),
                             }
                             ActionButton { name: "Create 10,000 rows", id: "runlots",
-                                onclick: move || items.set(Label::new_list(10_000)),
+                                onclick: move |_| items.set(Label::new_list(10_000)),
                             }
                             ActionButton { name: "Append 1,000 rows", id: "add",
-                                onclick: move || items.write().extend(Label::new_list(1_000)),
+                                onclick: move |_| items.write().extend(Label::new_list(1_000)),
                             }
                             ActionButton { name: "Update every 10th row", id: "update",
-                                onclick: move || items.write().iter_mut().step_by(10).for_each(|item| item.labels[2] = "!!!"),
+                                onclick: move |_| items.write().iter_mut().step_by(10).for_each(|item| item.labels[2] = "!!!"),
                             }
                             ActionButton { name: "Clear", id: "clear",
-                                onclick: move || items.write().clear(),
+                                onclick: move |_| items.write().clear(),
                             }
                             ActionButton { name: "Swap rows", id: "swaprows",
-                                onclick: move || items.write().swap(0, 998),
+                                onclick: move |_| items.write().swap(0, 998),
                             }
                         }
                     }
@@ -91,7 +91,7 @@ fn app(cx: Scope) -> Element {
 struct ActionButtonProps<'a> {
     name: &'a str,
     id: &'a str,
-    onclick: &'a dyn Fn(),
+    onclick: EventHandler<'a, ()>,
 }
 
 fn ActionButton<'a>(cx: Scope<'a, ActionButtonProps<'a>>) -> Element {
@@ -102,7 +102,7 @@ fn ActionButton<'a>(cx: Scope<'a, ActionButtonProps<'a>>) -> Element {
                 class:"btn btn-primary btn-block",
                 r#type: "button",
                 id: "{cx.props.id}",
-                onclick: move |_| (cx.props.onclick)(),
+                onclick: move |_| cx.props.onclick.call(()),
 
                 "{cx.props.name}"
             }

+ 2 - 4
examples/pattern_model.rs

@@ -15,8 +15,6 @@
 //! the RefCell will panic and crash. You can use `try_get_mut` or `.modify` to avoid this problem, or just not hold two
 //! RefMuts at the same time.
 
-use std::sync::Arc;
-
 use dioxus::desktop::wry::application::dpi::LogicalSize;
 use dioxus::events::*;
 use dioxus::prelude::*;
@@ -117,7 +115,7 @@ fn app(cx: Scope) -> Element {
 #[derive(Props)]
 struct CalculatorKeyProps<'a> {
     name: &'a str,
-    onclick: &'a dyn Fn(MouseEvent),
+    onclick: EventHandler<'a, MouseEvent>,
     children: Element<'a>,
 }
 
@@ -125,7 +123,7 @@ fn CalculatorKey<'a>(cx: Scope<'a, CalculatorKeyProps<'a>>) -> Element {
     cx.render(rsx! {
         button {
             class: "calculator-key {cx.props.name}",
-            onclick: move |e| (cx.props.onclick)(e),
+            onclick: move |e| cx.props.onclick.call(e),
             &cx.props.children
         }
     })

+ 1 - 1
packages/core-macro/src/rsx/component.rs

@@ -165,7 +165,7 @@ impl ToTokens for ContentField {
                 __cx.raw_text(format_args_f!(#s)).0
             }),
             ContentField::OnHandlerRaw(e) => tokens.append_all(quote! {
-                __cx.bump().alloc(#e)
+                __cx.event_handler(#e)
             }),
         }
     }

+ 22 - 11
packages/core/src/nodes.rs

@@ -316,29 +316,33 @@ pub struct Listener<'bump> {
     pub event: &'static str,
 
     /// The actual callback that the user specified
-    pub(crate) callback: EventHandler<'bump>,
+    pub(crate) callback: InternalHandler<'bump>,
 }
 
-/// The callback based into element event listeners.
-pub struct EventHandler<'bump> {
-    pub callback: &'bump RefCell<Option<ListenerCallback<'bump>>>,
+pub type InternalHandler<'bump> = &'bump RefCell<Option<InternalListenerCallback<'bump>>>;
+type InternalListenerCallback<'bump> = BumpBox<'bump, dyn FnMut(AnyEvent) + 'bump>;
+
+type ExternalListenerCallback<'bump, T> = BumpBox<'bump, dyn FnMut(T) + 'bump>;
+
+/// The callback based through the `rsx!` macro.
+pub struct EventHandler<'bump, T = ()> {
+    pub callback: &'bump RefCell<Option<ExternalListenerCallback<'bump, T>>>,
 }
 
-impl EventHandler<'_> {
-    pub fn call(&self, event: AnyEvent) {
+impl<T> EventHandler<'_, T> {
+    pub fn call(&self, event: T) {
         if let Some(callback) = self.callback.borrow_mut().as_mut() {
             callback(event);
         }
     }
+
     pub fn release(&self) {
         self.callback.replace(None);
     }
 }
 
-type ListenerCallback<'bump> = BumpBox<'bump, dyn FnMut(AnyEvent) + 'bump>;
-
-impl Copy for EventHandler<'_> {}
-impl Clone for EventHandler<'_> {
+impl<T> Copy for EventHandler<'_, T> {}
+impl<T> Clone for EventHandler<'_, T> {
     fn clone(&self) -> Self {
         Self {
             callback: self.callback,
@@ -551,7 +555,7 @@ impl<'a> NodeFactory<'a> {
         VNode::Component(vcomp)
     }
 
-    pub fn listener(self, event: &'static str, callback: EventHandler<'a>) -> Listener<'a> {
+    pub fn listener(self, event: &'static str, callback: InternalHandler<'a>) -> Listener<'a> {
         Listener {
             event,
             mounted_node: Cell::new(None),
@@ -643,6 +647,13 @@ impl<'a> NodeFactory<'a> {
             })))
         }
     }
+
+    pub fn event_handler<T>(self, f: impl FnMut(T) + 'a) -> EventHandler<'a, T> {
+        let handler: &mut dyn FnMut(T) = self.bump.alloc(f);
+        let caller = unsafe { BumpBox::from_raw(handler as *mut dyn FnMut(T)) };
+        let callback = self.bump.alloc(RefCell::new(Some(caller)));
+        EventHandler { callback }
+    }
 }
 
 impl Debug for NodeFactory<'_> {

+ 2 - 2
packages/core/src/scopes.rs

@@ -212,7 +212,7 @@ impl ScopeArena {
             items
                 .listeners
                 .drain(..)
-                .for_each(|listener| drop(listener.callback.callback.borrow_mut().take()));
+                .for_each(|listener| drop(listener.callback.borrow_mut().take()));
         }
     }
 
@@ -300,7 +300,7 @@ impl ScopeArena {
                                 break;
                             }
 
-                            let mut cb = listener.callback.callback.borrow_mut();
+                            let mut cb = listener.callback.borrow_mut();
                             if let Some(cb) = cb.as_mut() {
                                 // todo: arcs are pretty heavy to clone
                                 // we really want to convert arc to rc

+ 1 - 1
packages/hooks/src/useref.rs

@@ -1,5 +1,5 @@
 use std::{
-    cell::{Cell, Ref, RefCell, RefMut},
+    cell::{Ref, RefCell, RefMut},
     rc::Rc,
 };
 

+ 1 - 4
packages/html/src/events.rs

@@ -43,10 +43,7 @@ pub mod on {
                         // ie copy
                         let shortname: &'static str = &event_name[2..];
 
-                        let handler = EventHandler {
-                            callback: bump.alloc(std::cell::RefCell::new(Some(callback))),
-                        };
-
+                        let handler = bump.alloc(std::cell::RefCell::new(Some(callback)));
                         factory.listener(shortname, handler)
                     }
                 )*