From 8e4072e2764452a263ccd6b65f54708964866152 Mon Sep 17 00:00:00 2001 From: Maciej Hirsz Date: Tue, 28 Mar 2023 13:50:02 +0100 Subject: [PATCH] Use `unmount` and `replace_with` on Mountable to avoid DynAnchor path --- crates/kobold/src/branching.rs | 19 ++++++++++++++++++- crates/kobold/src/diff.rs | 23 ++++++++++++++++------- crates/kobold/src/lib.rs | 8 ++++++++ crates/kobold/src/list.rs | 4 ++-- crates/kobold/src/value.rs | 5 +---- examples/todomvc/src/main.rs | 2 -- 6 files changed, 45 insertions(+), 16 deletions(-) diff --git a/crates/kobold/src/branching.rs b/crates/kobold/src/branching.rs index f6638606..a981aa18 100644 --- a/crates/kobold/src/branching.rs +++ b/crates/kobold/src/branching.rs @@ -90,6 +90,7 @@ //! } //! ``` +use wasm_bindgen::JsValue; use web_sys::Node; use crate::dom::{self, Anchor, DynAnchor}; @@ -152,6 +153,22 @@ macro_rules! branch { )* } } + + fn replace_with(&self, new: &JsValue) { + match self { + $( + $name::$var(p) => p.replace_with(new), + )* + } + } + + fn unmount(&self) { + match self { + $( + $name::$var(p) => p.unmount(), + )* + } + } } }; @@ -207,7 +224,7 @@ impl View for Option { (html, old) => { let new = html.build(); - old.anchor().replace_with(new.js()); + old.replace_with(new.js()); *old = new; } diff --git a/crates/kobold/src/diff.rs b/crates/kobold/src/diff.rs index ee184e0d..32002ae6 100644 --- a/crates/kobold/src/diff.rs +++ b/crates/kobold/src/diff.rs @@ -9,7 +9,8 @@ use std::ops::Deref; use web_sys::Node; use crate::attribute::AttributeView; -use crate::value::IntoText; +use crate::dom::TextContent; +use crate::value::{IntoText, Value}; use crate::{Mountable, View}; /// This is a wrapper around a `view` that will prevent updates to it, unless @@ -238,30 +239,38 @@ macro_rules! impl_no_diff { impl View for $name where - T: IntoText + Copy, + T: Value + IntoText + Copy, { type Product = Node; - fn build(self) -> Self::Product { + fn build(self) -> Node { self.into_text() } - fn update(self, _: &mut Self::Product) {} + fn update(self, node: &mut Node) { + if $update { + self.0.set_prop(TextContent, node); + } + } } impl AttributeView

for $name where - T: AttributeView

, + T: Value

, { type Product = (); fn build(self) {} fn build_in(self, prop: P, node: &Node) { - self.0.build_in(prop, node); + self.0.set_prop(prop, node); } - fn update_in(self, _: P, _: &Node, _: &mut ()) {} + fn update_in(self, prop: P, node: &Node, _: &mut ()) { + if $update { + self.0.set_prop(prop, node); + } + } } impl Diff for $name diff --git a/crates/kobold/src/lib.rs b/crates/kobold/src/lib.rs index 487559f7..a69e4c9c 100644 --- a/crates/kobold/src/lib.rs +++ b/crates/kobold/src/lib.rs @@ -424,6 +424,14 @@ pub trait Mountable: 'static { fn js(&self) -> &JsValue { self.anchor().as_ref() } + + fn unmount(&self) { + self.anchor().unmount(); + } + + fn replace_with(&self, new: &JsValue) { + self.anchor().replace_with(new); + } } /// Start the Kobold app by mounting given [`View`](View) in the document `body`. diff --git a/crates/kobold/src/list.rs b/crates/kobold/src/list.rs index ea7ccc21..2c693a98 100644 --- a/crates/kobold/src/list.rs +++ b/crates/kobold/src/list.rs @@ -6,7 +6,7 @@ use web_sys::Node; -use crate::dom::{Anchor, Fragment, FragmentBuilder}; +use crate::dom::{Fragment, FragmentBuilder}; use crate::{Mountable, View}; /// Wrapper type that implements `View` for iterators. Use the [`list`](ListIteratorExt::list) @@ -82,7 +82,7 @@ where if p.visible > updated { for old in p.list[updated..p.visible].iter() { - old.anchor().unmount(); + old.unmount(); } p.visible = updated; } else { diff --git a/crates/kobold/src/value.rs b/crates/kobold/src/value.rs index fa761186..f83d038b 100644 --- a/crates/kobold/src/value.rs +++ b/crates/kobold/src/value.rs @@ -88,10 +88,7 @@ impl View for String { fn build(self) -> Self::Product { let node = self.as_str().into_text(); - TextProduct { - memo: self, - node, - } + TextProduct { memo: self, node } } fn update(self, p: &mut Self::Product) { diff --git a/examples/todomvc/src/main.rs b/examples/todomvc/src/main.rs index fd89d607..3168ac00 100644 --- a/examples/todomvc/src/main.rs +++ b/examples/todomvc/src/main.rs @@ -86,7 +86,6 @@ fn EntryInput(state: &Hook) -> impl View + '_ { mod test { use super::*; - #[component] fn ToggleAll(active_count: usize, state: &Hook) -> impl View + '_ { bind! { state: @@ -98,7 +97,6 @@ mod test {