mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
chore: get create working and simplify dynamic nodes
This commit is contained in:
parent
16a521a601
commit
3c19def550
16 changed files with 168 additions and 173 deletions
|
@ -30,7 +30,7 @@ fn app(cx: Scope) -> Element {
|
|||
}
|
||||
|
||||
fn BlogPost(cx: Scope) -> Element {
|
||||
let post = dioxus_router::use_route(&cx).last_segment()?;
|
||||
let post = dioxus_router::use_route(&cx).last_segment().unwrap();
|
||||
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
|
@ -46,7 +46,7 @@ struct Query {
|
|||
}
|
||||
|
||||
fn User(cx: Scope) -> Element {
|
||||
let post = dioxus_router::use_route(&cx).last_segment()?;
|
||||
let post = dioxus_router::use_route(&cx).last_segment().unwrap();
|
||||
|
||||
let query = dioxus_router::use_route(&cx)
|
||||
.query::<Query>()
|
||||
|
|
|
@ -165,13 +165,13 @@ fn app(cx: Scope) -> Element {
|
|||
|
||||
// Can pass in props directly as an expression
|
||||
{
|
||||
let props = TallerProps {a: "hello", children: Default::default()};
|
||||
let props = TallerProps {a: "hello", children: cx.render(rsx!(()))};
|
||||
rsx!(Taller { ..props })
|
||||
}
|
||||
|
||||
// Spreading can also be overridden manually
|
||||
Taller {
|
||||
..TallerProps { a: "ballin!", children: Default::default() },
|
||||
..TallerProps { a: "ballin!", children: cx.render(rsx!(()) )},
|
||||
a: "not ballin!"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
factory::RenderReturn, nodes::VNode, virtual_dom::VirtualDom, AttributeValue, DynamicNode,
|
||||
ScopeId, VFragment,
|
||||
ScopeId,
|
||||
};
|
||||
use bumpalo::boxed::Box as BumpBox;
|
||||
|
||||
|
@ -101,7 +101,7 @@ impl VirtualDom {
|
|||
for (idx, _) in node.template.roots.iter().enumerate() {
|
||||
match node.dynamic_root(idx) {
|
||||
Some(DynamicNode::Component(c)) => self.drop_scope(c.scope.get().unwrap()),
|
||||
Some(DynamicNode::Fragment(VFragment::NonEmpty(nodes))) => {
|
||||
Some(DynamicNode::Fragment(nodes)) => {
|
||||
for node in *nodes {
|
||||
self.drop_scope_inner(node);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use std::cell::Cell;
|
||||
|
||||
use crate::factory::RenderReturn;
|
||||
use crate::innerlude::{VComponent, VFragment, VText};
|
||||
use crate::innerlude::{VComponent, VText};
|
||||
use crate::mutations::Mutation;
|
||||
use crate::mutations::Mutation::*;
|
||||
use crate::nodes::VNode;
|
||||
use crate::nodes::{DynamicNode, TemplateNode};
|
||||
use crate::virtual_dom::VirtualDom;
|
||||
use crate::{AttributeValue, ScopeId, SuspenseContext, TemplateAttribute};
|
||||
use crate::{AttributeValue, ElementId, ScopeId, SuspenseContext, TemplateAttribute};
|
||||
|
||||
impl<'b> VirtualDom {
|
||||
/// Create a new template [`VNode`] and write it to the [`Mutations`] buffer.
|
||||
|
@ -55,15 +57,14 @@ impl<'b> VirtualDom {
|
|||
1
|
||||
}
|
||||
|
||||
DynamicNode::Fragment(VFragment::Empty(slot)) => {
|
||||
DynamicNode::Placeholder(slot) => {
|
||||
let id = self.next_element(template, template.template.node_paths[*id]);
|
||||
slot.set(id);
|
||||
self.mutations.push(CreatePlaceholder { id });
|
||||
1
|
||||
}
|
||||
|
||||
DynamicNode::Fragment(VFragment::NonEmpty(_))
|
||||
| DynamicNode::Component { .. } => {
|
||||
DynamicNode::Fragment(_) | DynamicNode::Component { .. } => {
|
||||
self.create_dynamic_node(template, &template.dynamic_nodes[*id], *id)
|
||||
}
|
||||
}
|
||||
|
@ -309,7 +310,8 @@ impl<'b> VirtualDom {
|
|||
use DynamicNode::*;
|
||||
match node {
|
||||
Text(text) => self.create_dynamic_text(template, text, idx),
|
||||
Fragment(frag) => self.create_fragment(frag, template, idx),
|
||||
Fragment(frag) => self.create_fragment(frag),
|
||||
Placeholder(frag) => self.create_placeholder(frag, template, idx),
|
||||
Component(component) => self.create_component_node(template, component, idx),
|
||||
}
|
||||
}
|
||||
|
@ -340,34 +342,30 @@ impl<'b> VirtualDom {
|
|||
0
|
||||
}
|
||||
|
||||
pub(crate) fn create_fragment(
|
||||
pub(crate) fn create_placeholder(
|
||||
&mut self,
|
||||
frag: &'b VFragment<'b>,
|
||||
slot: &Cell<ElementId>,
|
||||
template: &'b VNode<'b>,
|
||||
idx: usize,
|
||||
) -> usize {
|
||||
match frag {
|
||||
VFragment::NonEmpty(nodes) => {
|
||||
nodes.iter().fold(0, |acc, child| acc + self.create(child))
|
||||
}
|
||||
// Allocate a dynamic element reference for this text node
|
||||
let id = self.next_element(template, template.template.node_paths[idx]);
|
||||
|
||||
VFragment::Empty(slot) => {
|
||||
// Allocate a dynamic element reference for this text node
|
||||
let id = self.next_element(template, template.template.node_paths[idx]);
|
||||
// Make sure the text node is assigned to the correct element
|
||||
slot.set(id);
|
||||
|
||||
// Make sure the text node is assigned to the correct element
|
||||
slot.set(id);
|
||||
// Assign the ID to the existing node in the template
|
||||
self.mutations.push(AssignId {
|
||||
path: &template.template.node_paths[idx][1..],
|
||||
id,
|
||||
});
|
||||
|
||||
// Assign the ID to the existing node in the template
|
||||
self.mutations.push(AssignId {
|
||||
path: &template.template.node_paths[idx][1..],
|
||||
id,
|
||||
});
|
||||
// Since the placeholder is already in the DOM, we don't create any new nodes
|
||||
0
|
||||
}
|
||||
|
||||
// Since the placeholder is already in the DOM, we don't create any new nodes
|
||||
0
|
||||
}
|
||||
}
|
||||
pub(crate) fn create_fragment(&mut self, nodes: &'b [VNode<'b>]) -> usize {
|
||||
nodes.iter().fold(0, |acc, child| acc + self.create(child))
|
||||
}
|
||||
|
||||
pub(super) fn create_component_node(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
arena::ElementId,
|
||||
factory::RenderReturn,
|
||||
innerlude::{DirtyScope, VComponent, VFragment, VText},
|
||||
innerlude::{DirtyScope, VComponent, VText},
|
||||
mutations::Mutation,
|
||||
nodes::{DynamicNode, VNode},
|
||||
scopes::ScopeId,
|
||||
|
@ -10,7 +10,6 @@ use crate::{
|
|||
};
|
||||
|
||||
use fxhash::{FxHashMap, FxHashSet};
|
||||
use std::cell::Cell;
|
||||
use DynamicNode::*;
|
||||
|
||||
impl<'b> VirtualDom {
|
||||
|
@ -101,7 +100,7 @@ impl<'b> VirtualDom {
|
|||
{
|
||||
match (left_node, right_node) {
|
||||
(Text(left), Text(right)) => self.diff_vtext(left, right),
|
||||
(Fragment(left), Fragment(right)) => self.diff_vfragment(left, right),
|
||||
(Fragment(left), Fragment(right)) => self.diff_non_empty_fragment(left, right),
|
||||
(Component(left), Component(right)) => {
|
||||
self.diff_vcomponent(left, right, right_template, idx)
|
||||
}
|
||||
|
@ -231,40 +230,6 @@ impl<'b> VirtualDom {
|
|||
}
|
||||
}
|
||||
|
||||
fn diff_vfragment(&mut self, left: &'b VFragment<'b>, right: &'b VFragment<'b>) {
|
||||
use VFragment::*;
|
||||
match (left, right) {
|
||||
(Empty(l), Empty(r)) => r.set(l.get()),
|
||||
(Empty(l), NonEmpty(r)) => self.replace_placeholder_with_nodes(l, r),
|
||||
(NonEmpty(l), Empty(r)) => self.replace_nodes_with_placeholder(l, r),
|
||||
(NonEmpty(old), NonEmpty(new)) => self.diff_non_empty_fragment(new, old),
|
||||
}
|
||||
}
|
||||
|
||||
fn replace_placeholder_with_nodes(&mut self, l: &'b Cell<ElementId>, r: &'b [VNode<'b>]) {
|
||||
let m = self.create_children(r);
|
||||
let id = l.get();
|
||||
self.mutations.push(Mutation::ReplaceWith { id, m });
|
||||
self.reclaim(id);
|
||||
}
|
||||
|
||||
fn replace_nodes_with_placeholder(&mut self, l: &'b [VNode<'b>], r: &'b Cell<ElementId>) {
|
||||
// Create the placeholder first, ensuring we get a dedicated ID for the placeholder
|
||||
let placeholder = self.next_element(&l[0], &[]);
|
||||
r.set(placeholder);
|
||||
self.mutations
|
||||
.push(Mutation::CreatePlaceholder { id: placeholder });
|
||||
|
||||
// Remove the old nodes, except for onea
|
||||
let first = self.replace_inner(&l[0]);
|
||||
self.remove_nodes(&l[1..]);
|
||||
|
||||
self.mutations
|
||||
.push(Mutation::ReplaceWith { id: first, m: 1 });
|
||||
|
||||
self.try_reclaim(first);
|
||||
}
|
||||
|
||||
/// Remove all the top-level nodes, returning the firstmost root ElementId
|
||||
///
|
||||
/// All IDs will be garbage collected
|
||||
|
@ -272,8 +237,8 @@ impl<'b> VirtualDom {
|
|||
let id = match node.dynamic_root(0) {
|
||||
None => node.root_ids[0].get(),
|
||||
Some(Text(t)) => t.id.get(),
|
||||
Some(Fragment(VFragment::Empty(e))) => e.get(),
|
||||
Some(Fragment(VFragment::NonEmpty(nodes))) => {
|
||||
Some(Placeholder(e)) => e.get(),
|
||||
Some(Fragment(nodes)) => {
|
||||
let id = self.replace_inner(&nodes[0]);
|
||||
self.remove_nodes(&nodes[1..]);
|
||||
id
|
||||
|
@ -317,10 +282,8 @@ impl<'b> VirtualDom {
|
|||
};
|
||||
}
|
||||
Text(t) => self.reclaim(t.id.get()),
|
||||
Fragment(VFragment::Empty(t)) => self.reclaim(t.get()),
|
||||
Fragment(VFragment::NonEmpty(nodes)) => {
|
||||
nodes.iter().for_each(|node| self.clean_up_node(node))
|
||||
}
|
||||
Placeholder(t) => self.reclaim(t.get()),
|
||||
Fragment(nodes) => nodes.iter().for_each(|node| self.clean_up_node(node)),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -351,12 +314,12 @@ impl<'b> VirtualDom {
|
|||
self.mutations.push(Mutation::Remove { id });
|
||||
self.reclaim(id);
|
||||
}
|
||||
Some(Fragment(VFragment::Empty(e))) => {
|
||||
Some(Placeholder(e)) => {
|
||||
let id = e.get();
|
||||
self.mutations.push(Mutation::Remove { id });
|
||||
self.reclaim(id);
|
||||
}
|
||||
Some(Fragment(VFragment::NonEmpty(nodes))) => self.remove_nodes(nodes),
|
||||
Some(Fragment(nodes)) => self.remove_nodes(nodes),
|
||||
Some(Component(comp)) => {
|
||||
let scope = comp.scope.get().unwrap();
|
||||
match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } {
|
||||
|
@ -750,8 +713,8 @@ impl<'b> VirtualDom {
|
|||
for (idx, _) in node.template.roots.iter().enumerate() {
|
||||
let id = match node.dynamic_root(idx) {
|
||||
Some(Text(t)) => t.id.get(),
|
||||
Some(Fragment(VFragment::Empty(t))) => t.get(),
|
||||
Some(Fragment(VFragment::NonEmpty(t))) => return self.remove_nodes(t),
|
||||
Some(Placeholder(t)) => t.get(),
|
||||
Some(Fragment(t)) => return self.remove_nodes(t),
|
||||
Some(Component(comp)) => return self.remove_component(comp.scope.get().unwrap()),
|
||||
None => node.root_ids[idx].get(),
|
||||
};
|
||||
|
@ -793,12 +756,12 @@ impl<'b> VirtualDom {
|
|||
self.mutations.push(Mutation::PushRoot { id: t.id.get() });
|
||||
onstack += 1;
|
||||
}
|
||||
Some(Fragment(VFragment::Empty(t))) => {
|
||||
Some(Placeholder(t)) => {
|
||||
self.mutations.push(Mutation::PushRoot { id: t.get() });
|
||||
onstack += 1;
|
||||
}
|
||||
Some(Fragment(VFragment::NonEmpty(t))) => {
|
||||
for node in *t {
|
||||
Some(Fragment(nodes)) => {
|
||||
for node in *nodes {
|
||||
onstack += self.push_all_real_nodes(node);
|
||||
}
|
||||
}
|
||||
|
@ -842,8 +805,8 @@ impl<'b> VirtualDom {
|
|||
match node.dynamic_root(0) {
|
||||
None => node.root_ids[0].get(),
|
||||
Some(Text(t)) => t.id.get(),
|
||||
Some(Fragment(VFragment::NonEmpty(t))) => self.find_first_element(&t[0]),
|
||||
Some(Fragment(VFragment::Empty(t))) => t.get(),
|
||||
Some(Fragment(t)) => self.find_first_element(&t[0]),
|
||||
Some(Placeholder(t)) => t.get(),
|
||||
Some(Component(comp)) => {
|
||||
let scope = comp.scope.get().unwrap();
|
||||
match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } {
|
||||
|
@ -858,8 +821,8 @@ impl<'b> VirtualDom {
|
|||
match node.dynamic_root(node.template.roots.len() - 1) {
|
||||
None => node.root_ids.last().unwrap().get(),
|
||||
Some(Text(t)) => t.id.get(),
|
||||
Some(Fragment(VFragment::NonEmpty(t))) => self.find_last_element(t.last().unwrap()),
|
||||
Some(Fragment(VFragment::Empty(t))) => t.get(),
|
||||
Some(Fragment(t)) => self.find_last_element(t.last().unwrap()),
|
||||
Some(Placeholder(t)) => t.get(),
|
||||
Some(Component(comp)) => {
|
||||
let scope = comp.scope.get().unwrap();
|
||||
match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } {
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::future::Future;
|
|||
use crate::{
|
||||
any_props::{AnyProps, VProps},
|
||||
arena::ElementId,
|
||||
innerlude::{DynamicNode, EventHandler, VComponent, VFragment, VText},
|
||||
innerlude::{DynamicNode, EventHandler, VComponent, VText},
|
||||
Attribute, AttributeValue, Element, LazyNodes, Properties, Scope, ScopeState, VNode,
|
||||
};
|
||||
|
||||
|
@ -148,12 +148,20 @@ pub trait IntoDynNode<'a, A = ()> {
|
|||
|
||||
impl<'a> IntoDynNode<'a> for () {
|
||||
fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
|
||||
DynamicNode::Fragment(VFragment::Empty(Cell::new(ElementId(0))))
|
||||
DynamicNode::placeholder()
|
||||
}
|
||||
}
|
||||
impl<'a> IntoDynNode<'a> for VNode<'a> {
|
||||
fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
|
||||
DynamicNode::Fragment(VFragment::NonEmpty(_cx.bump().alloc([self])))
|
||||
DynamicNode::Fragment(_cx.bump().alloc([self]))
|
||||
}
|
||||
}
|
||||
impl<'a> IntoDynNode<'a> for Element<'a> {
|
||||
fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
|
||||
match self {
|
||||
Ok(val) => val.into_vnode(_cx),
|
||||
_ => DynamicNode::placeholder(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,7 +169,7 @@ impl<'a, T: IntoDynNode<'a>> IntoDynNode<'a> for Option<T> {
|
|||
fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
|
||||
match self {
|
||||
Some(val) => val.into_vnode(_cx),
|
||||
None => DynamicNode::Fragment(VFragment::Empty(Cell::new(ElementId(0)))),
|
||||
None => DynamicNode::placeholder(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,14 +178,14 @@ impl<'a> IntoDynNode<'a> for &Element<'a> {
|
|||
fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
|
||||
match self.as_ref() {
|
||||
Ok(val) => val.clone().into_vnode(_cx),
|
||||
_ => DynamicNode::Fragment(VFragment::Empty(Cell::new(ElementId(0)))),
|
||||
_ => DynamicNode::placeholder(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> IntoDynNode<'a> for LazyNodes<'a, 'b> {
|
||||
fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> {
|
||||
DynamicNode::Fragment(VFragment::NonEmpty(cx.bump().alloc([self.call(cx)])))
|
||||
DynamicNode::Fragment(cx.bump().alloc([self.call(cx)]))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,14 +209,14 @@ impl<'b> IntoDynNode<'b> for Arguments<'_> {
|
|||
|
||||
impl<'a> IntoDynNode<'a> for &'a VNode<'a> {
|
||||
fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
|
||||
DynamicNode::Fragment(VFragment::NonEmpty(_cx.bump().alloc([VNode {
|
||||
DynamicNode::Fragment(_cx.bump().alloc([VNode {
|
||||
parent: self.parent,
|
||||
template: self.template,
|
||||
root_ids: self.root_ids,
|
||||
key: self.key,
|
||||
dynamic_nodes: self.dynamic_nodes,
|
||||
dynamic_attrs: self.dynamic_attrs,
|
||||
}])))
|
||||
}]))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,8 +251,8 @@ where
|
|||
let children = nodes.into_bump_slice();
|
||||
|
||||
match children.len() {
|
||||
0 => DynamicNode::Fragment(VFragment::Empty(Cell::new(ElementId(0)))),
|
||||
_ => DynamicNode::Fragment(VFragment::NonEmpty(children)),
|
||||
0 => DynamicNode::placeholder(),
|
||||
_ => DynamicNode::Fragment(children),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ pub(crate) mod innerlude {
|
|||
pub use crate::dirty_scope::*;
|
||||
pub use crate::error_boundary::*;
|
||||
pub use crate::events::*;
|
||||
pub use crate::factory::RenderReturn;
|
||||
pub use crate::fragment::*;
|
||||
pub use crate::lazynodes::*;
|
||||
pub use crate::mutations::*;
|
||||
|
@ -87,6 +88,7 @@ pub use crate::innerlude::{
|
|||
Mutations,
|
||||
NodeFactory,
|
||||
Properties,
|
||||
RenderReturn,
|
||||
Scope,
|
||||
ScopeId,
|
||||
ScopeState,
|
||||
|
@ -99,7 +101,6 @@ pub use crate::innerlude::{
|
|||
TemplateNode,
|
||||
UiEvent,
|
||||
VComponent,
|
||||
VFragment,
|
||||
VNode,
|
||||
VText,
|
||||
VirtualDom,
|
||||
|
|
|
@ -150,10 +150,6 @@ pub enum Mutation<'a> {
|
|||
id: ElementId,
|
||||
},
|
||||
|
||||
SetInnerText {
|
||||
value: &'a str,
|
||||
},
|
||||
|
||||
SetText {
|
||||
value: &'a str,
|
||||
id: ElementId,
|
||||
|
|
|
@ -89,13 +89,17 @@ pub enum TemplateNode<'a> {
|
|||
pub enum DynamicNode<'a> {
|
||||
Component(VComponent<'a>),
|
||||
Text(VText<'a>),
|
||||
Fragment(VFragment<'a>),
|
||||
Placeholder(Cell<ElementId>),
|
||||
Fragment(&'a [VNode<'a>]),
|
||||
}
|
||||
|
||||
impl<'a> DynamicNode<'a> {
|
||||
pub fn is_component(&self) -> bool {
|
||||
matches!(self, DynamicNode::Component(_))
|
||||
}
|
||||
pub fn placeholder() -> Self {
|
||||
Self::Placeholder(Cell::new(ElementId(0)))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VComponent<'a> {
|
||||
|
@ -122,12 +126,6 @@ pub struct VText<'a> {
|
|||
pub value: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum VFragment<'a> {
|
||||
Empty(Cell<ElementId>),
|
||||
NonEmpty(&'a [VNode<'a>]),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TemplateAttribute<'a> {
|
||||
Static {
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
scheduler::RcWake,
|
||||
scopes::{ScopeId, ScopeState},
|
||||
virtual_dom::VirtualDom,
|
||||
AttributeValue, DynamicNode, VFragment, VNode,
|
||||
AttributeValue, DynamicNode, VNode,
|
||||
};
|
||||
use futures_util::FutureExt;
|
||||
use std::{
|
||||
|
@ -75,7 +75,7 @@ impl VirtualDom {
|
|||
c.props.set(None);
|
||||
}
|
||||
}
|
||||
DynamicNode::Fragment(VFragment::NonEmpty(f)) => {
|
||||
DynamicNode::Fragment(f) => {
|
||||
for node in *f {
|
||||
self.ensure_drop_safety_inner(node);
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ impl DesktopController {
|
|||
let name = value.event.clone();
|
||||
let el_id = ElementId(value.mounted_dom_id);
|
||||
if let Some(evt) = decode_event(value) {
|
||||
dom.handle_event(&name, evt, el_id, true, EventPriority::Medium);
|
||||
dom.handle_event(&name, evt, el_id, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,16 +132,13 @@ export class Interpreter {
|
|||
this.nodes[root] = node;
|
||||
this.stack.push(node);
|
||||
}
|
||||
CreateElement(tag, root) {
|
||||
CreateElement(tag) {
|
||||
const el = document.createElement(tag);
|
||||
this.nodes[root] = el;
|
||||
this.stack.push(el);
|
||||
}
|
||||
CreateElementNs(tag, root, ns) {
|
||||
console.log("creating element", tag, root, ns);
|
||||
CreateElementNs(tag, ns) {
|
||||
let el = document.createElementNS(ns, tag);
|
||||
this.stack.push(el);
|
||||
this.nodes[root] = el;
|
||||
}
|
||||
CreatePlaceholder(root) {
|
||||
let el = document.createElement("pre");
|
||||
|
@ -149,6 +146,11 @@ export class Interpreter {
|
|||
this.stack.push(el);
|
||||
this.nodes[root] = el;
|
||||
}
|
||||
CreateStaticPlaceholder() {
|
||||
let el = document.createElement("pre");
|
||||
el.hidden = true;
|
||||
this.stack.push(el);
|
||||
}
|
||||
NewEventListener(event_name, root, handler, bubbles) {
|
||||
const element = this.nodes[root];
|
||||
element.setAttribute("data-dioxus-id", `${root}`);
|
||||
|
@ -162,9 +164,16 @@ export class Interpreter {
|
|||
SetText(root, text) {
|
||||
this.nodes[root].textContent = text;
|
||||
}
|
||||
SetAttribute(root, field, value, ns) {
|
||||
SetAttribute(id, field, value, ns) {
|
||||
const node = this.nodes[id];
|
||||
this.SetAttributeInner(node, field, value, ns);
|
||||
}
|
||||
SetStaticAttribute(field, value, ns) {
|
||||
const node = this.top();
|
||||
this.SetAttributeInner(node, field, value, ns);
|
||||
}
|
||||
SetAttributeInner(node, field, value, ns) {
|
||||
const name = field;
|
||||
const node = this.nodes[root];
|
||||
if (ns === "style") {
|
||||
// ????? why do we need to do this
|
||||
if (node.style === undefined) {
|
||||
|
@ -248,9 +257,9 @@ export class Interpreter {
|
|||
let node = this.LoadChild(path);
|
||||
node.replaceWith(...els);
|
||||
}
|
||||
LoadTemplate(name, index) {
|
||||
console.log("loading template", name, index);
|
||||
LoadTemplate(name, index, id) {
|
||||
let node = this.templates[name][index].cloneNode(true);
|
||||
this.nodes[id] = node;
|
||||
this.stack.push(node);
|
||||
}
|
||||
SaveTemplate(name, m) {
|
||||
|
@ -265,24 +274,38 @@ export class Interpreter {
|
|||
this.AssignId(edit.path, edit.id);
|
||||
break;
|
||||
case "CreateElement":
|
||||
if (edit.namespace !== null && edit.namespace !== undefined) {
|
||||
this.CreateElementNs(edit.name, edit.id, edit.namespace);
|
||||
} else {
|
||||
this.CreateElement(edit.name, edit.id);
|
||||
}
|
||||
this.CreateElement(edit.name);
|
||||
break;
|
||||
case "CreateElementNs":
|
||||
this.CreateElementNs(edit.name, edit.namespace);
|
||||
break;
|
||||
case "CreatePlaceholder":
|
||||
this.CreatePlaceholder(edit.id);
|
||||
break;
|
||||
case "CreateTextNode":
|
||||
case "CreateStaticText":
|
||||
this.CreateTextNode(edit.value);
|
||||
break;
|
||||
case "CreateStaticPlaceholder":
|
||||
this.CreateStaticPlaceholder();
|
||||
break;
|
||||
case "CreateTextPlaceholder":
|
||||
this.CreateRawText("placeholder");
|
||||
break;
|
||||
case "CreateStaticText":
|
||||
this.CreateRawText(edit.value);
|
||||
break;
|
||||
case "CreateTextNode":
|
||||
this.CreateTextNode(edit.value);
|
||||
break;
|
||||
case "HydrateText":
|
||||
this.HydrateText(edit.path, edit.value, edit.id);
|
||||
break;
|
||||
case "LoadTemplate":
|
||||
this.LoadTemplate(edit.name, edit.index);
|
||||
break;
|
||||
case "SaveTemplate":
|
||||
this.SaveTemplate(edit.name, edit.m);
|
||||
break;
|
||||
case "PushRoot":
|
||||
this.PushRoot(edit.id);
|
||||
break;
|
||||
|
@ -293,29 +316,29 @@ export class Interpreter {
|
|||
this.ReplacePlaceholder(edit.path, edit.m);
|
||||
break;
|
||||
case "InsertAfter":
|
||||
this.InsertAfter(edit.id, edit.n);
|
||||
this.InsertAfter(edit.id, edit.m);
|
||||
break;
|
||||
case "InsertBefore":
|
||||
this.InsertBefore(edit.id, edit.n);
|
||||
this.InsertBefore(edit.id, edit.m);
|
||||
break;
|
||||
case "Remove":
|
||||
this.Remove(edit.id);
|
||||
break;
|
||||
case "LoadTemplate":
|
||||
this.LoadTemplate(edit.name, edit.index);
|
||||
break;
|
||||
case "SaveTemplate":
|
||||
this.SaveTemplate(edit.name, edit.m);
|
||||
break;
|
||||
case "CreateElementNs":
|
||||
this.CreateElementNs(edit.name, edit.id, edit.ns);
|
||||
break;
|
||||
case "SetText":
|
||||
this.SetText(edit.id, edit.value);
|
||||
break;
|
||||
case "SetAttribute":
|
||||
this.SetAttribute(edit.id, edit.name, edit.value, edit.ns);
|
||||
break;
|
||||
case "SetStaticAttribute":
|
||||
this.SetStaticAttribute(edit.name, edit.value, edit.ns);
|
||||
break;
|
||||
case "SetBoolAttribute":
|
||||
this.SetAttribute(edit.id, edit.name, edit.value, edit.ns);
|
||||
break;
|
||||
case "SetInnerText":
|
||||
console.log("Set inner text?");
|
||||
break;
|
||||
case "RemoveAttribute":
|
||||
this.RemoveAttribute(edit.id, edit.name, edit.ns);
|
||||
break;
|
||||
|
|
|
@ -47,5 +47,5 @@ pub fn Redirect<'a>(cx: Scope<'a, RedirectProps<'a>>) -> Element {
|
|||
router.replace_route(cx.props.to, None, None);
|
||||
}
|
||||
|
||||
None
|
||||
cx.render(rsx!(()))
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@ pub struct RouteProps<'a> {
|
|||
pub fn Route<'a>(cx: Scope<'a, RouteProps<'a>>) -> Element {
|
||||
let router_root = cx
|
||||
.use_hook(|| cx.consume_context::<Arc<RouterCore>>())
|
||||
.as_ref()?;
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
|
||||
cx.use_hook(|| {
|
||||
// create a bigger, better, longer route if one above us exists
|
||||
|
@ -55,6 +56,6 @@ pub fn Route<'a>(cx: Scope<'a, RouteProps<'a>>) -> Element {
|
|||
cx.render(rsx!(&cx.props.children))
|
||||
} else {
|
||||
log::trace!("Route should *not* render: {:?}", cx.scope_id());
|
||||
None
|
||||
cx.render(rsx!(()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::fmt::Write;
|
|||
|
||||
pub struct StringCache {
|
||||
pub segments: Vec<Segment>,
|
||||
pub template: Template<'static>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -40,6 +41,7 @@ impl StringCache {
|
|||
|
||||
Ok(Self {
|
||||
segments: chain.segments,
|
||||
template: template.template,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::cache::Segment;
|
||||
use dioxus_core::{prelude::*, AttributeValue, DynamicNode, VText};
|
||||
use dioxus_core::{prelude::*, AttributeValue, DynamicNode, RenderReturn, VText};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Write;
|
||||
use std::rc::Rc;
|
||||
|
@ -9,7 +9,7 @@ use crate::cache::StringCache;
|
|||
/// A virtualdom renderer that caches the templates it has seen for faster rendering
|
||||
#[derive(Default)]
|
||||
pub struct SsrRender {
|
||||
template_cache: HashMap<Template<'static>, Rc<StringCache>>,
|
||||
template_cache: HashMap<&'static str, Rc<StringCache>>,
|
||||
}
|
||||
|
||||
impl SsrRender {
|
||||
|
@ -18,7 +18,11 @@ impl SsrRender {
|
|||
let root = scope.root_node();
|
||||
|
||||
let mut out = String::new();
|
||||
// self.render_template(&mut out, dom, root).unwrap();
|
||||
|
||||
match root {
|
||||
RenderReturn::Sync(Ok(node)) => self.render_template(&mut out, dom, node).unwrap(),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
out
|
||||
}
|
||||
|
@ -31,7 +35,7 @@ impl SsrRender {
|
|||
) -> std::fmt::Result {
|
||||
let entry = self
|
||||
.template_cache
|
||||
.entry(template.template)
|
||||
.entry(template.template.id)
|
||||
.or_insert_with(|| Rc::new(StringCache::from_template(template).unwrap()))
|
||||
.clone();
|
||||
|
||||
|
@ -46,37 +50,38 @@ impl SsrRender {
|
|||
};
|
||||
}
|
||||
Segment::Node(idx) => match &template.dynamic_nodes[*idx] {
|
||||
DynamicNode::Component(_) => todo!(),
|
||||
DynamicNode::Text(_) => todo!(),
|
||||
DynamicNode::Fragment(_) => todo!(),
|
||||
DynamicNode::Placeholder(_) => todo!(),
|
||||
// todo!()
|
||||
// DynamicNode::Text(VText { id, value }) => {
|
||||
// // in SSR, we are concerned that we can't hunt down the right text node since they might get merged
|
||||
// // if !*inner {
|
||||
// write!(buf, "<!--#-->")?;
|
||||
// // }
|
||||
DynamicNode::Component(node) => {
|
||||
let id = node.scope.get().unwrap();
|
||||
let scope = dom.get_scope(id).unwrap();
|
||||
let node = scope.root_node();
|
||||
match node {
|
||||
RenderReturn::Sync(Ok(node)) => self.render_template(buf, dom, node)?,
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
DynamicNode::Text(text) => {
|
||||
// in SSR, we are concerned that we can't hunt down the right text node since they might get merged
|
||||
// if !*inner {
|
||||
// write!(buf, "<!--#-->")?;
|
||||
// }
|
||||
|
||||
// // todo: escape the text
|
||||
// write!(buf, "{}", value)?;
|
||||
// todo: escape the text
|
||||
write!(buf, "{}", text.value)?;
|
||||
|
||||
// // if !*inner {
|
||||
// write!(buf, "<!--/#-->")?;
|
||||
// // }
|
||||
// }
|
||||
// DynamicNode::Fragment { nodes, .. } => {
|
||||
// for child in *nodes {
|
||||
// self.render_template(buf, dom, child)?;
|
||||
// }
|
||||
// }
|
||||
// DynamicNode::Component { scope, .. } => {
|
||||
// let id = scope.get().unwrap();
|
||||
// let scope = dom.get_scope(id).unwrap();
|
||||
// self.render_template(buf, dom, scope.root_node())?;
|
||||
// }
|
||||
// DynamicNode::Placeholder(_el) => {
|
||||
// write!(buf, "<!--placeholder-->")?;
|
||||
// }
|
||||
// if !*inner {
|
||||
// write!(buf, "<!--/#-->")?;
|
||||
// }
|
||||
}
|
||||
DynamicNode::Fragment(nodes) => {
|
||||
for child in *nodes {
|
||||
self.render_template(buf, dom, child)?;
|
||||
}
|
||||
}
|
||||
|
||||
DynamicNode::Placeholder(_el) => {
|
||||
// todo write a placeholder if in pre-render mode
|
||||
// write!(buf, "<!--placeholder-->")?;
|
||||
}
|
||||
},
|
||||
|
||||
Segment::PreRendered(contents) => buf.push_str(contents),
|
||||
|
|
Loading…
Reference in a new issue