diff --git a/src/dom_types.rs b/src/dom_types.rs index 8ed5831a1..c60831b15 100644 --- a/src/dom_types.rs +++ b/src/dom_types.rs @@ -437,6 +437,13 @@ impl UpdateEl> for Tag { } } +impl UpdateEl> for Optimize { + // This, or some other mechanism seems to work for String too... note sure why. + fn update(self, el: &mut El) { + el.optimizations.push(self) + } +} + /// Similar to tag population. macro_rules! make_attrs { // Create shortcut macros for any element; populate these functions in this module. @@ -1019,6 +1026,13 @@ make_tags! { Style => "style", View => "view" } +/// WIP that marks elements in ways to improve diffing and rendering efficiency. +#[derive(Copy, Clone, Debug)] +pub enum Optimize { + Key(u32), // Helps correctly match children, prevening unecessary rerenders + Static, // unimplemented, and possibly unecessary +} + /// An component in our virtual DOM. #[derive(Debug)] // todo: Custom debug implementation where children are on new lines and indented. pub struct El { @@ -1052,6 +1066,7 @@ pub struct El { // Lifecycle hooks pub hooks: LifecycleHooks, pub empty: bool, // Indicates not to render anything. + optimizations: Vec } type HookFn = Box; @@ -1102,7 +1117,8 @@ impl El { // static: false, // static_to_parent: false, hooks: LifecycleHooks::default(), - empty: false + empty: false, + optimizations: Vec::new(), } } @@ -1171,6 +1187,16 @@ impl El { self.text = Some(text.into()) } + /// Shortcut for finding the key, if one exists + pub fn key(&self) -> Option { + for o in &self.optimizations { + if let Optimize::Key(key) = o { + return Some(*key) + } + } + None + } + /// Output the HTML of this node, including all its children, recursively. fn _html(&self) -> String { let text = self.text.clone().unwrap_or_default(); @@ -1209,6 +1235,7 @@ impl El { // control: self.control, hooks: LifecycleHooks::default(), empty: false, + optimizations: Vec::new(), } } @@ -1244,6 +1271,7 @@ impl Clone for El { namespace: self.namespace.clone(), hooks: LifecycleHooks::default(), empty: self.empty, + optimizations: self.optimizations.clone(), } } } diff --git a/src/lib.rs b/src/lib.rs index 1b11c4984..35c93ba85 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,7 +83,7 @@ pub mod prelude { pub use crate::{ dom_types::{ did_mount, did_update, input_ev, keyboard_ev, mouse_ev, raw_ev, simple_ev, - will_unmount, At, El, Ev, Tag, UpdateEl, + will_unmount, At, El, Ev, Optimize::Key, Tag, UpdateEl, }, shortcuts::*, // appears not to work. // vdom::{Update, Update::Render, Update::Skip, Update::RenderThen}, diff --git a/src/routing.rs b/src/routing.rs index 3966b1269..9e85d26bd 100644 --- a/src/routing.rs +++ b/src/routing.rs @@ -76,9 +76,9 @@ fn get_search() -> String { /// For setting up landing page routing. Unlike normal routing, we can't rely /// on the popstate state, so must go off path, hash, and search directly. pub fn initial(app: App, routes: fn(&Url) -> Ms) -> App -where - Ms: Clone + 'static, - Mdl: 'static, + where + Ms: Clone + 'static, + Mdl: 'static, { let raw_path = get_path(); let path_ref: Vec<&str> = raw_path.split('/').collect(); @@ -211,12 +211,10 @@ pub fn setup_popstate_listener(app: &App, routes: fn(&Url) -> app.data.popstate_closure.replace(Some(closure)); } -/// Set up a listener that intercepts clicks on and