mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
Significant perf improvements
This commit is contained in:
parent
d1b5e652c1
commit
d6c007dcc4
3 changed files with 64 additions and 15 deletions
|
@ -1,12 +1,38 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use leptos_reactive::Scope;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Attribute {
|
||||
String(String),
|
||||
Fn(Box<dyn Fn() -> Attribute>),
|
||||
Fn(Rc<dyn Fn() -> Attribute>),
|
||||
Option(Option<String>),
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
impl PartialEq for Attribute {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::String(l0), Self::String(r0)) => l0 == r0,
|
||||
(Self::Fn(_), Self::Fn(_)) => false,
|
||||
(Self::Option(l0), Self::Option(r0)) => l0 == r0,
|
||||
(Self::Bool(l0), Self::Bool(r0)) => l0 == r0,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Attribute {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::String(arg0) => f.debug_tuple("String").field(arg0).finish(),
|
||||
Self::Fn(_) => f.debug_tuple("Fn").finish(),
|
||||
Self::Option(arg0) => f.debug_tuple("Option").field(arg0).finish(),
|
||||
Self::Bool(arg0) => f.debug_tuple("Bool").field(arg0).finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoAttribute {
|
||||
fn into_attribute(self, cx: Scope) -> Attribute;
|
||||
}
|
||||
|
@ -35,7 +61,7 @@ where
|
|||
U: IntoAttribute,
|
||||
{
|
||||
fn into_attribute(self, cx: Scope) -> Attribute {
|
||||
let modified_fn = Box::new(move || (self)().into_attribute(cx));
|
||||
let modified_fn = Rc::new(move || (self)().into_attribute(cx));
|
||||
Attribute::Fn(modified_fn)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ macro_rules! prop_type {
|
|||
};
|
||||
}
|
||||
|
||||
prop_type!(JsValue);
|
||||
prop_type!(String);
|
||||
prop_type!(&String);
|
||||
prop_type!(&str);
|
||||
|
|
|
@ -40,7 +40,13 @@ pub fn attribute(cx: Scope, el: &web_sys::Element, attr_name: &'static str, valu
|
|||
match value {
|
||||
Attribute::Fn(f) => {
|
||||
let el = el.clone();
|
||||
create_render_effect(cx, move |_| attribute_expression(&el, attr_name, f()));
|
||||
create_render_effect(cx, move |old| {
|
||||
let new = f();
|
||||
if old.as_ref() != Some(&new) {
|
||||
attribute_expression(&el, attr_name, new.clone());
|
||||
}
|
||||
new
|
||||
});
|
||||
}
|
||||
_ => attribute_expression(el, attr_name, value),
|
||||
}
|
||||
|
@ -62,7 +68,13 @@ pub fn property(cx: Scope, el: &web_sys::Element, prop_name: &'static str, value
|
|||
match value {
|
||||
Property::Fn(f) => {
|
||||
let el = el.clone();
|
||||
create_render_effect(cx, move |_| property_expression(&el, prop_name, f()));
|
||||
create_render_effect(cx, move |old| {
|
||||
let new = f();
|
||||
if old.as_ref() != Some(&new) && !(old == None && new == JsValue::UNDEFINED) {
|
||||
property_expression(&el, prop_name, new.clone())
|
||||
}
|
||||
new
|
||||
});
|
||||
}
|
||||
Property::Value(value) => property_expression(el, prop_name, value),
|
||||
}
|
||||
|
@ -76,7 +88,13 @@ pub fn class(cx: Scope, el: &web_sys::Element, class_name: &'static str, value:
|
|||
match value {
|
||||
Class::Fn(f) => {
|
||||
let el = el.clone();
|
||||
create_render_effect(cx, move |_| class_expression(&el, class_name, f()));
|
||||
create_render_effect(cx, move |old| {
|
||||
let new = f();
|
||||
if old.as_ref() != Some(&new) && (old.is_some() || new) {
|
||||
class_expression(&el, class_name, new)
|
||||
}
|
||||
new
|
||||
});
|
||||
}
|
||||
Class::Value(value) => class_expression(el, class_name, value),
|
||||
}
|
||||
|
@ -106,16 +124,21 @@ pub fn insert(
|
|||
.unwrap_or(Child::Null);
|
||||
|
||||
let mut value = f();
|
||||
while let Child::Fn(f) = value {
|
||||
value = f();
|
||||
}
|
||||
|
||||
Some(insert_expression(
|
||||
parent.clone().unchecked_into(),
|
||||
&value,
|
||||
current,
|
||||
&before,
|
||||
))
|
||||
if current != value {
|
||||
while let Child::Fn(f) = value {
|
||||
value = f();
|
||||
}
|
||||
|
||||
Some(insert_expression(
|
||||
parent.clone().unchecked_into(),
|
||||
&value,
|
||||
current,
|
||||
&before,
|
||||
))
|
||||
} else {
|
||||
Some(current)
|
||||
}
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
|
@ -157,7 +180,6 @@ pub fn insert_expression(
|
|||
// if the new value is null, clean children out of the parent up to the marker node
|
||||
Child::Null => {
|
||||
if let Child::Node(old_node) = current {
|
||||
crate::debug_warn!("just remove the node");
|
||||
remove_child(&parent, &old_node);
|
||||
Child::Null
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue