浏览代码

chore: tweak generic arguments and iterators in rsx

Jonathan Kelley 2 年之前
父节点
当前提交
e09b6bf813

+ 1 - 1
examples/eval.rs

@@ -16,7 +16,7 @@ fn app(cx: Scope) -> Element {
                 oninput: move |e| script.set(e.value.clone()),
             }
             button {
-                onclick: move |_| eval(script),
+                onclick: move |_| eval(script.to_string()),
                 "Execute"
             }
         }

+ 1 - 1
examples/framework_benchmark.rs

@@ -72,7 +72,7 @@ fn app(cx: Scope) -> Element {
                             td { class:"col-md-1" }
                             td { class:"col-md-1", "{item.key}" }
                             td { class:"col-md-1", onclick: move |_| selected.set(Some(id)),
-                                a { class: "lbl", item.labels }
+                                a { class: "lbl", "{item.labels[0]}{item.labels[1]}{item.labels[2]}" }
                             }
                             td { class: "col-md-1",
                                 a { class: "remove", onclick: move |_| { items.write().remove(id); },

+ 19 - 0
examples/generic_component.rs

@@ -0,0 +1,19 @@
+use std::fmt::Display;
+
+use dioxus::prelude::*;
+
+fn main() {
+    dioxus_desktop::launch(app);
+}
+
+fn app(cx: Scope) -> Element {
+    cx.render(rsx! {
+        generic_child::<i32>{}
+    })
+}
+
+fn generic_child<T>(cx: Scope) -> Element {
+    cx.render(rsx! {
+        div {}
+    })
+}

+ 1 - 1
examples/rsx_usage.rs

@@ -183,7 +183,7 @@ fn app(cx: Scope) -> Element {
 
             // Components can be generic too
             // This component takes i32 type to give you typed input
-            TypedInput::<TypedInputProps<i32>> {}
+            TypedInput::<i32> {}
 
             // Type inference can be used too
             TypedInput { initial: 10.0 }

+ 3 - 2
examples/simple_list.rs

@@ -8,11 +8,12 @@ fn app(cx: Scope) -> Element {
     cx.render(rsx!(
         // Use Map directly to lazily pull elements
         (0..10).map(|f| rsx! { "{f}" }),
-        // Collect into an intermediate collection if necessary
+        // Collect into an intermediate collection if necessary, and call into_iter
         ["a", "b", "c"]
             .into_iter()
             .map(|f| rsx! { "{f}" })
-            .collect::<Vec<_>>(),
+            .collect::<Vec<_>>()
+            .into_iter(),
         // Use optionals
         Some(rsx! { "Some" }),
     ))

+ 61 - 59
packages/core/src/factory.rs

@@ -41,25 +41,11 @@ impl ScopeState {
         }
     }
 
-    pub fn fragment_from_iter<'a, 'c, I, J>(
+    pub fn fragment_from_iter<'a, 'c, I>(
         &'a self,
-        node_iter: impl IntoVNode<'a, I, J> + 'c,
+        node_iter: impl IntoDynNode<'a, I> + 'c,
     ) -> DynamicNode {
         node_iter.into_vnode(self)
-
-        // let mut bump_vec = bumpalo::vec![in self.bump();];
-
-        // for item in it {
-        //     bump_vec.push(item.into_vnode(self));
-        // }
-
-        // match bump_vec.len() {
-        //     0 => DynamicNode::Placeholder(Cell::new(ElementId(0))),
-        //     _ => DynamicNode::Fragment {
-        //         inner: false,
-        //         nodes: bump_vec.into_bump_slice(),
-        //     },
-        // }
     }
 
     /// Create a new [`Attribute`]
@@ -155,46 +141,65 @@ impl<'a> RenderReturn<'a> {
     }
 }
 
-pub trait IntoVNode<'a, A = (), J = ()> {
+pub trait IntoDynNode<'a, A = ()> {
     fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a>;
 }
 
-impl<'a, 'b> IntoVNode<'a> for VNode<'a> {
+impl<'a, 'b> IntoDynNode<'a> for () {
     fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
         todo!()
         // self
     }
 }
+impl<'a, 'b> IntoDynNode<'a> for VNode<'a> {
+    fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
+        // DynamicNode::Fragment { nodes: cx., inner: () }
+        todo!()
+    }
+}
 
-impl<'a, 'b> IntoVNode<'a> for LazyNodes<'a, 'b> {
-    fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> {
+impl<'a, 'b, T: IntoDynNode<'a>> IntoDynNode<'a> for Option<T> {
+    fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
+        // DynamicNode::Fragment { nodes: cx., inner: () }
         todo!()
-        // self.call(cx)
     }
 }
 
-impl<'b> IntoVNode<'_> for &'b str {
-    fn into_vnode(self, cx: &ScopeState) -> DynamicNode {
-        // cx.text(format_args!("{}", self))
+impl<'a, 'b, T: IntoDynNode<'a>> IntoDynNode<'a> for &Option<T> {
+    fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
+        // DynamicNode::Fragment { nodes: cx., inner: () }
         todo!()
     }
 }
 
-impl IntoVNode<'_> for String {
+impl<'a, 'b> IntoDynNode<'a> for LazyNodes<'a, 'b> {
+    fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> {
+        DynamicNode::Fragment {
+            nodes: cx.bump().alloc([self.call(cx)]),
+            inner: false,
+        }
+    }
+}
+
+impl<'b> IntoDynNode<'_> for &'b str {
     fn into_vnode(self, cx: &ScopeState) -> DynamicNode {
-        // cx.text(format_args!("{}", self))
-        todo!()
+        cx.text(format_args!("{}", self))
     }
 }
 
-impl<'b> IntoVNode<'b> for Arguments<'_> {
+impl IntoDynNode<'_> for String {
+    fn into_vnode(self, cx: &ScopeState) -> DynamicNode {
+        cx.text(format_args!("{}", self))
+    }
+}
+
+impl<'b> IntoDynNode<'b> for Arguments<'_> {
     fn into_vnode(self, cx: &'b ScopeState) -> DynamicNode<'b> {
-        // cx.text(self)
-        todo!()
+        cx.text(self)
     }
 }
 
-impl<'a, 'b> IntoVNode<'a> for &VNode<'a> {
+impl<'a, 'b> IntoDynNode<'a> for &VNode<'a> {
     fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
         todo!()
         // VNode {
@@ -209,46 +214,43 @@ impl<'a, 'b> IntoVNode<'a> for &VNode<'a> {
     }
 }
 
+pub trait IntoTemplate<'a> {
+    fn into_template(self, _cx: &'a ScopeState) -> VNode<'a>;
+}
+impl<'a, 'b> IntoTemplate<'a> for VNode<'a> {
+    fn into_template(self, _cx: &'a ScopeState) -> VNode<'a> {
+        self
+    }
+}
+impl<'a, 'b> IntoTemplate<'a> for LazyNodes<'a, 'b> {
+    fn into_template(self, cx: &'a ScopeState) -> VNode<'a> {
+        self.call(cx)
+    }
+}
+
 // Note that we're using the E as a generic but this is never crafted anyways.
 pub struct FromNodeIterator;
-impl<'a, T, I, E> IntoVNode<'a, FromNodeIterator, E> for T
+impl<'a, T, I> IntoDynNode<'a, FromNodeIterator> for T
 where
-    T: IntoIterator<Item = I>,
-    I: IntoVNode<'a, E>,
+    T: Iterator<Item = I>,
+    I: IntoTemplate<'a>,
 {
     fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> {
         let mut nodes = bumpalo::collections::Vec::new_in(cx.bump());
 
         for node in self {
-            nodes.push(node.into_vnode(cx));
+            nodes.push(node.into_template(cx));
         }
 
         let children = nodes.into_bump_slice();
 
-        // if cfg!(debug_assertions) && children.len() > 1 && children.last().unwrap().key().is_none()
-        // {
-        // let bt = backtrace::Backtrace::new();
-        // let bt = "no backtrace available";
-
-        // // todo: make the backtrace prettier or remove it altogether
-        // log::error!(
-        //     r#"
-        //     Warning: Each child in an array or iterator should have a unique "key" prop.
-        //     Not providing a key will lead to poor performance with lists.
-        //     See docs.rs/dioxus for more information.
-        //     -------------
-        //     {:?}
-        //     "#,
-        //     bt
-        // );
-        // }
-
-        todo!()
-        // VNode::Fragment(cx.bump.alloc(VFragment {
-        //     children,
-        //     placeholder: Default::default(),
-        //     key: None,
-        // }))
+        match children.len() {
+            0 => DynamicNode::Placeholder(Cell::new(ElementId(0))),
+            _ => DynamicNode::Fragment {
+                inner: false,
+                nodes: children,
+            },
+        }
     }
 }
 

+ 7 - 2
packages/rsx/src/component.rs

@@ -154,7 +154,7 @@ impl ToTokens for Component {
             }
             None => {
                 let mut toks = match prop_gen_args {
-                    Some(gen_args) => quote! { fc_to_builder #gen_args(#name) },
+                    Some(gen_args) => quote! { fc_to_builder(#name #gen_args) },
                     None => quote! { fc_to_builder(#name) },
                 };
                 for field in &self.fields {
@@ -187,9 +187,14 @@ impl ToTokens for Component {
 
         let fn_name = self.name.segments.last().unwrap().ident.to_string();
 
+        let gen_name = match &self.prop_gen_args {
+            Some(gen) => quote! { #name #gen },
+            None => quote! { #name },
+        };
+
         tokens.append_all(quote! {
             __cx.component(
-                #name,
+                #gen_name,
                 #builder,
                 #fn_name
             )