1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
//! Abstraction over a rendering backend. #[cfg(feature = "dom")] pub mod dom_node; #[cfg(feature = "ssr")] pub mod ssr_node; use std::fmt; use std::hash::Hash; use wasm_bindgen::prelude::*; use web_sys::Event; #[cfg(feature = "dom")] pub use dom_node::*; #[cfg(feature = "ssr")] pub use ssr_node::*; /// Type of event handlers. pub type EventHandler = dyn Fn(Event); /// Abstraction over a rendering backend. /// /// You would probably use this trait as a trait bound when you want to accept any rendering /// backend. For example, components are often generic over [`GenericNode`] to be able to render to /// different backends. /// /// Note that components are **NOT** represented by [`GenericNode`]. Instead, components are /// _disappearing_, meaning that they are simply functions that generate [`GenericNode`]s inside a /// new reactive context. This means that there is no overhead whatsoever when using components. /// /// Sycamore ships with 2 rendering backends out of the box: /// * [`DomNode`] - Rendering in the browser (to real DOM nodes). /// * [`SsrNode`] - Render to a static string (often on the server side for Server Side Rendering, /// aka. SSR). /// /// To implement your own rendering backend, you will need to create a new struct which implements /// [`GenericNode`]. /// /// # Cloning /// /// [`GenericNode`]s should be cheaply cloneable (usually backed by a [`Rc`](std::rc::Rc) or other /// reference counted container) and preserve reference equality. pub trait GenericNode: fmt::Debug + Clone + PartialEq + Eq + Hash + 'static { /// Create a new element node. fn element(tag: &str) -> Self; /// Create a new text node. fn text_node(text: &str) -> Self; /// Create a marker (dummy) node. For [`DomNode`], this is implemented by creating an empty /// comment node. This is used, for example, in [`Keyed`](crate::flow::Keyed) and /// [`Indexed`](crate::flow::Indexed) for scenarios where you want to push a new item to the /// end of the list. If the list is empty, a dummy node is needed to store the position of /// the component. fn marker() -> Self; /// Sets an attribute on a node. fn set_attribute(&self, name: &str, value: &str); /// Sets the `class` attribute on a node. /// This should have the same outcome as calling `set_attribute("class", value)`. /// For [`DomNode`], this sets the `className` property directly which is about 2x faster (on Chrome). fn set_class_name(&self, value: &str); /// Sets a property on a node. fn set_property(&self, name: &str, value: &JsValue); /// Appends a child to the node's children. fn append_child(&self, child: &Self); /// Get the first child of the node. fn first_child(&self) -> Option<Self>; /// Insert a new child node to this node's children. If `reference_node` is `Some`, the child /// will be inserted before the reference node. Else if `None`, the child will be inserted /// at the end. fn insert_child_before(&self, new_node: &Self, reference_node: Option<&Self>); /// Remove a child node from this node's children. fn remove_child(&self, child: &Self); /// Replace a child node from this node's children with a new child node. fn replace_child(&self, old: &Self, new: &Self); /// Insert a new node before this node. fn insert_sibling_before(&self, child: &Self); /// Returns the parent node, or `None` if detached. fn parent_node(&self) -> Option<Self>; /// Returns the next sibling, or `None` if this node is the last sibling. fn next_sibling(&self) -> Option<Self>; /// Remove this node from the tree. fn remove_self(&self); /// Add a [`EventHandler`] to the event `name`. fn event(&self, name: &str, handler: Box<EventHandler>); /// Update inner text of the node. If the node has elements, all the elements are replaced with /// a new text node. fn update_inner_text(&self, text: &str); /// Create a deep clone of the node. fn clone_node(&self) -> Self; }