浏览代码

throttle history updates to 100ms

Evan Almloff 2 年之前
父节点
当前提交
bc063c58b7
共有 3 个文件被更改,包括 116 次插入4 次删除
  1. 70 0
      packages/router/src/components/router.rs
  2. 24 4
      packages/router/src/history/web.rs
  3. 22 0
      packages/router/src/router_cfg.rs

+ 70 - 0
packages/router/src/components/router.rs

@@ -14,6 +14,18 @@ pub struct RouterConfigFactory<R: Routable> {
     config: RefCell<Option<Box<dyn FnOnce() -> RouterConfig<R>>>>,
     config: RefCell<Option<Box<dyn FnOnce() -> RouterConfig<R>>>>,
 }
 }
 
 
+#[cfg(feature = "serde")]
+impl<R: Routable> Default for RouterConfigFactory<R>
+where
+    <R as FromStr>::Err: std::fmt::Display,
+    R: serde::Serialize + serde::de::DeserializeOwned,
+{
+    fn default() -> Self {
+        Self::from(RouterConfig::default)
+    }
+}
+
+#[cfg(not(feature = "serde"))]
 impl<R: Routable> Default for RouterConfigFactory<R>
 impl<R: Routable> Default for RouterConfigFactory<R>
 where
 where
     <R as FromStr>::Err: std::fmt::Display,
     <R as FromStr>::Err: std::fmt::Display,
@@ -31,19 +43,45 @@ impl<R: Routable, F: FnOnce() -> RouterConfig<R> + 'static> From<F> for RouterCo
     }
     }
 }
 }
 
 
+#[cfg(feature = "serde")]
 /// The props for [`GenericRouter`].
 /// The props for [`GenericRouter`].
 #[derive(Props)]
 #[derive(Props)]
 pub struct GenericRouterProps<R: Routable>
 pub struct GenericRouterProps<R: Routable>
 where
 where
     <R as FromStr>::Err: std::fmt::Display,
     <R as FromStr>::Err: std::fmt::Display,
+    R: serde::Serialize + serde::de::DeserializeOwned,
 {
 {
     #[props(default, into)]
     #[props(default, into)]
     config: RouterConfigFactory<R>,
     config: RouterConfigFactory<R>,
 }
 }
 
 
+#[cfg(not(feature = "serde"))]
+/// The props for [`GenericRouter`].
+#[derive(Props)]
+pub struct GenericRouterProps<R: Routable>
+where
+    <R as FromStr>::Err: std::fmt::Display,
+{
+    #[props(default, into)]
+    config: RouterConfigFactory<R>,
+}
+
+#[cfg(not(feature = "serde"))]
+impl<R: Routable> PartialEq for GenericRouterProps<R>
+where
+    <R as FromStr>::Err: std::fmt::Display,
+{
+    fn eq(&self, _: &Self) -> bool {
+        // prevent the router from re-rendering when the initial url or config changes
+        true
+    }
+}
+
+#[cfg(feature = "serde")]
 impl<R: Routable> PartialEq for GenericRouterProps<R>
 impl<R: Routable> PartialEq for GenericRouterProps<R>
 where
 where
     <R as FromStr>::Err: std::fmt::Display,
     <R as FromStr>::Err: std::fmt::Display,
+    R: serde::Serialize + serde::de::DeserializeOwned,
 {
 {
     fn eq(&self, _: &Self) -> bool {
     fn eq(&self, _: &Self) -> bool {
         // prevent the router from re-rendering when the initial url or config changes
         // prevent the router from re-rendering when the initial url or config changes
@@ -51,10 +89,42 @@ where
     }
     }
 }
 }
 
 
+#[cfg(not(feature = "serde"))]
+/// A component that renders the current route.
+pub fn GenericRouter<R: Routable + Clone>(cx: Scope<GenericRouterProps<R>>) -> Element
+where
+    <R as FromStr>::Err: std::fmt::Display,
+{
+    use_context_provider(cx, || {
+        #[allow(unreachable_code, unused_variables)]
+        if let Some(outer) = cx.consume_context::<GenericRouterContext<R>>() {
+            let msg = "Router components should not be nested within each other";
+            error!("{msg}, inner will be inactive and transparent");
+            #[cfg(debug_assertions)]
+            panic!("{}", msg);
+        }
+        let router = GenericRouterContext::new(
+            (cx.props
+                .config
+                .config
+                .take()
+                .expect("use_context_provider ran twice"))(),
+            cx.schedule_update_any(),
+        );
+        router
+    });
+
+    render! {
+        GenericOutlet::<R> {}
+    }
+}
+
+#[cfg(feature = "serde")]
 /// A component that renders the current route.
 /// A component that renders the current route.
 pub fn GenericRouter<R: Routable + Clone>(cx: Scope<GenericRouterProps<R>>) -> Element
 pub fn GenericRouter<R: Routable + Clone>(cx: Scope<GenericRouterProps<R>>) -> Element
 where
 where
     <R as FromStr>::Err: std::fmt::Display,
     <R as FromStr>::Err: std::fmt::Display,
+    R: serde::Serialize + serde::de::DeserializeOwned,
 {
 {
     use_context_provider(cx, || {
     use_context_provider(cx, || {
         #[allow(unreachable_code, unused_variables)]
         #[allow(unreachable_code, unused_variables)]

+ 24 - 4
packages/router/src/history/web.rs

@@ -104,8 +104,18 @@ impl<R: Routable> WebHistory<R> {
         let myself = Self::new_inner(
         let myself = Self::new_inner(
             prefix,
             prefix,
             do_scroll_restoration,
             do_scroll_restoration,
-            EventListener::new(&document, "scroll", move |_| {
-                update_scroll::<R>(&w, &h);
+            EventListener::new(&document, "scroll", {
+                let mut last_updated = 0.0;
+                move |evt| {
+                    // the time stamp in milliseconds
+                    let time_stamp = evt.time_stamp();
+                    // throttle the scroll event to 100ms
+                    if (time_stamp - last_updated) < 100.0 {
+                        return;
+                    }
+                    update_scroll::<R>(&w, &h);
+                    last_updated = time_stamp;
+                }
             }),
             }),
         );
         );
 
 
@@ -134,8 +144,18 @@ impl<R: Routable> WebHistory<R> {
         let myself = Self::new_inner(
         let myself = Self::new_inner(
             prefix,
             prefix,
             do_scroll_restoration,
             do_scroll_restoration,
-            EventListener::new(&document, "scroll", move |_| {
-                update_scroll::<R>(&w, &h);
+            EventListener::new(&document, "scroll", {
+                let mut last_updated = 0.0;
+                move |evt| {
+                    // the time stamp in milliseconds
+                    let time_stamp = evt.time_stamp();
+                    // throttle the scroll event to 100ms
+                    if (time_stamp - last_updated) < 100.0 {
+                        return;
+                    }
+                    update_scroll::<R>(&w, &h);
+                    last_updated = time_stamp;
+                }
             }),
             }),
         );
         );
 
 

+ 22 - 0
packages/router/src/router_cfg.rs

@@ -30,6 +30,28 @@ pub struct RouterConfig<R: Routable> {
     pub(crate) on_update: Option<RoutingCallback<R>>,
     pub(crate) on_update: Option<RoutingCallback<R>>,
 }
 }
 
 
+#[cfg(feature = "serde")]
+impl<R: Routable + Clone> Default for RouterConfig<R>
+where
+    <R as std::str::FromStr>::Err: std::fmt::Display,
+    R: serde::Serialize + serde::de::DeserializeOwned,
+{
+    fn default() -> Self {
+        Self {
+            failure_external_navigation: FailureExternalNavigation::<R>,
+            history: {
+                #[cfg(all(target_arch = "wasm32", feature = "web"))]
+                let history = Box::<WebHistory<R>>::default();
+                #[cfg(not(all(target_arch = "wasm32", feature = "web")))]
+                let history = Box::<MemoryHistory<R>>::default();
+                history
+            },
+            on_update: None,
+        }
+    }
+}
+
+#[cfg(not(feature = "serde"))]
 impl<R: Routable + Clone> Default for RouterConfig<R>
 impl<R: Routable + Clone> Default for RouterConfig<R>
 where
 where
     <R as std::str::FromStr>::Err: std::fmt::Display,
     <R as std::str::FromStr>::Err: std::fmt::Display,