mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 14:44:12 +00:00
feat: pull children out of component definition
This commit is contained in:
parent
f438bbcfd2
commit
2cf90b6903
4 changed files with 40 additions and 75 deletions
|
@ -161,12 +161,22 @@ impl ToTokens for Component {
|
|||
None => {
|
||||
let mut toks = quote! { fc_to_builder(#name) };
|
||||
for field in &self.body {
|
||||
if field.name == "key" {
|
||||
has_key = Some(field);
|
||||
} else {
|
||||
toks.append_all(quote! {#field})
|
||||
match field.name.to_string().as_str() {
|
||||
"key" => {
|
||||
//
|
||||
has_key = Some(field);
|
||||
}
|
||||
_ => toks.append_all(quote! {#field}),
|
||||
}
|
||||
}
|
||||
|
||||
if !self.children.is_empty() {
|
||||
let childs = &self.children;
|
||||
toks.append_all(quote! {
|
||||
.children(ScopeChildren::new(__cx.fragment_from_iter([ #( #childs ),* ])))
|
||||
});
|
||||
}
|
||||
|
||||
toks.append_all(quote! {
|
||||
.build()
|
||||
});
|
||||
|
@ -182,17 +192,13 @@ impl ToTokens for Component {
|
|||
None => quote! { None },
|
||||
};
|
||||
|
||||
let childs = &self.children;
|
||||
let children = quote! {
|
||||
[ #( #childs ),* ]
|
||||
};
|
||||
// #children
|
||||
|
||||
tokens.append_all(quote! {
|
||||
__cx.component(
|
||||
#name,
|
||||
#builder,
|
||||
#key_token,
|
||||
#children
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -230,15 +230,10 @@ fn Child2<'a>((cx, props): Scope<'a, Child2Props>) -> Element<'a> {
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
let b = cx.bump();
|
||||
let node: &'a VNode<'a> = b.alloc(node);
|
||||
|
||||
let children = Children { pthru: node };
|
||||
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
ChildrenComp {
|
||||
children: children
|
||||
div {}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -246,46 +241,14 @@ fn Child2<'a>((cx, props): Scope<'a, Child2Props>) -> Element<'a> {
|
|||
|
||||
#[derive(Props)]
|
||||
struct ChildrenTest<'a> {
|
||||
children: Children<'a>,
|
||||
}
|
||||
|
||||
struct Children<'a> {
|
||||
pthru: &'a VNode<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Clone for Children<'a> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { pthru: self.pthru }
|
||||
}
|
||||
}
|
||||
impl<'a> Copy for Children<'a> {}
|
||||
|
||||
impl<'a> IntoVNode<'a> for Children<'a> {
|
||||
fn into_vnode(self, _: NodeFactory<'a>) -> VNode<'a> {
|
||||
match self.pthru {
|
||||
VNode::Text(f) => VNode::Text(*f),
|
||||
VNode::Element(e) => VNode::Element(*e),
|
||||
VNode::Component(c) => VNode::Component(*c),
|
||||
VNode::Suspended(s) => VNode::Suspended(*s),
|
||||
VNode::Anchor(a) => VNode::Anchor(a),
|
||||
VNode::Fragment(f) => VNode::Fragment(VFragment {
|
||||
children: f.children,
|
||||
is_static: f.is_static,
|
||||
key: f.key,
|
||||
}),
|
||||
}
|
||||
}
|
||||
children: ScopeChildren<'a>,
|
||||
}
|
||||
|
||||
fn ChildrenComp<'a>((cx, props): Scope<'a, ChildrenTest<'a>>) -> Element<'a> {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
div {
|
||||
|
||||
// if the node's id is already assigned, then it's being passed in as a child
|
||||
// in these instances, we don't worry about re-checking the node?
|
||||
|
||||
{Some(props.children)}
|
||||
{&props.children}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -187,11 +187,7 @@ impl Debug for VNode<'_> {
|
|||
|
||||
VNode::Fragment(frag) => write!(s, "VFragment {{ children: {:?} }}", frag.children),
|
||||
VNode::Suspended { .. } => write!(s, "VSuspended"),
|
||||
VNode::Component(comp) => write!(
|
||||
s,
|
||||
"VComponent {{ fc: {:?}, children: {:?} }}",
|
||||
comp.user_fc, comp.children
|
||||
),
|
||||
VNode::Component(comp) => write!(s, "VComponent {{ fc: {:?}}}", comp.user_fc),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -331,8 +327,6 @@ pub struct VComponent<'src> {
|
|||
|
||||
pub(crate) caller: &'src dyn for<'b> Fn(&'b ScopeInner) -> Element<'b>,
|
||||
|
||||
pub(crate) children: &'src [VNode<'src>],
|
||||
|
||||
pub(crate) comparator: Option<&'src dyn Fn(&VComponent) -> bool>,
|
||||
|
||||
pub(crate) drop_props: RefCell<Option<BumpBox<'src, dyn FnMut()>>>,
|
||||
|
@ -483,20 +477,16 @@ impl<'a> NodeFactory<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn component<P, V>(
|
||||
pub fn component<P>(
|
||||
&self,
|
||||
component: fn(Scope<'a, P>) -> Element<'a>,
|
||||
props: P,
|
||||
key: Option<Arguments>,
|
||||
children: V,
|
||||
) -> VNode<'a>
|
||||
where
|
||||
P: Properties + 'a,
|
||||
V: AsRef<[VNode<'a>]> + 'a,
|
||||
{
|
||||
let bump = self.bump();
|
||||
let children: &'a V = bump.alloc(children);
|
||||
let children = children.as_ref();
|
||||
let props = bump.alloc(props);
|
||||
let raw_props = props as *mut P as *mut ();
|
||||
let user_fc = component as *const ();
|
||||
|
@ -518,7 +508,7 @@ impl<'a> NodeFactory<'a> {
|
|||
|
||||
// It's only okay to memoize if there are no children and the props can be memoized
|
||||
// Implementing memoize is unsafe and done automatically with the props trait
|
||||
matches!((props_memoized, children.is_empty()), (true, true))
|
||||
props_memoized
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -549,8 +539,6 @@ impl<'a> NodeFactory<'a> {
|
|||
RefCell::new(Some(drop_props))
|
||||
};
|
||||
|
||||
let is_static = children.is_empty() && P::IS_STATIC && key.is_none();
|
||||
|
||||
let key = key.map(|f| self.raw_text(f).0);
|
||||
|
||||
let caller: &'a mut dyn for<'b> Fn(&'b ScopeInner) -> Element<'b> =
|
||||
|
@ -565,17 +553,14 @@ impl<'a> NodeFactory<'a> {
|
|||
unsafe { std::mem::transmute(res) }
|
||||
});
|
||||
|
||||
let can_memoize = children.is_empty() && P::IS_STATIC;
|
||||
|
||||
VNode::Component(bump.alloc(VComponent {
|
||||
user_fc,
|
||||
comparator,
|
||||
raw_props,
|
||||
children,
|
||||
caller,
|
||||
is_static,
|
||||
is_static: P::IS_STATIC,
|
||||
key,
|
||||
can_memoize,
|
||||
can_memoize: P::IS_STATIC,
|
||||
drop_props,
|
||||
associated_scope: Cell::new(None),
|
||||
}))
|
||||
|
@ -770,6 +755,18 @@ pub struct ScopeChildren<'a> {
|
|||
root: Option<VNode<'a>>,
|
||||
}
|
||||
|
||||
impl Default for ScopeChildren<'_> {
|
||||
fn default() -> Self {
|
||||
Self { root: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ScopeChildren<'a> {
|
||||
pub fn new(root: VNode<'a>) -> Self {
|
||||
Self { root: Some(root) }
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for &ScopeChildren<'_> {
|
||||
type Item = Self;
|
||||
|
||||
|
|
|
@ -208,12 +208,11 @@ fn create_simple() {
|
|||
#[test]
|
||||
fn create_components() {
|
||||
static App: FC<()> = |(cx, props)| {
|
||||
todo!()
|
||||
// cx.render(rsx! {
|
||||
// Child { "abc1" }
|
||||
// Child { "abc2" }
|
||||
// Child { "abc3" }
|
||||
// })
|
||||
cx.render(rsx! {
|
||||
Child { "abc1" }
|
||||
Child { "abc2" }
|
||||
Child { "abc3" }
|
||||
})
|
||||
};
|
||||
|
||||
#[derive(Props)]
|
||||
|
|
Loading…
Reference in a new issue