Changing to use document fragments for dynamic child replacement
This commit is contained in:
parent
e5957b7831
commit
e4b2347149
|
@ -38,6 +38,7 @@ features = [
|
|||
"CssStyleRule",
|
||||
"CssStyleSheet",
|
||||
"Document",
|
||||
"DocumentFragment",
|
||||
"DomTokenList",
|
||||
"Element",
|
||||
"Event",
|
||||
|
|
|
@ -28,10 +28,10 @@ impl<A: Discard> IRemove for A {
|
|||
}
|
||||
|
||||
|
||||
pub(crate) struct InsertCallback(Box<IInsertCallback>);
|
||||
pub(crate) struct InsertCallback(Box<dyn IInsertCallback>);
|
||||
|
||||
// TODO is there a more efficient way of doing this ?
|
||||
pub(crate) struct RemoveCallback(Box<IRemove>);
|
||||
pub(crate) struct RemoveCallback(Box<dyn IRemove>);
|
||||
|
||||
impl std::fmt::Debug for InsertCallback {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
|
@ -76,25 +76,27 @@ impl Callbacks {
|
|||
// TODO runtime checks to make sure this isn't called multiple times ?
|
||||
#[inline]
|
||||
pub(crate) fn trigger_after_insert(&mut self) {
|
||||
let mut callbacks = Callbacks::new();
|
||||
if !self.after_insert.is_empty() {
|
||||
let mut callbacks = Callbacks::new();
|
||||
|
||||
// TODO verify that this is correct
|
||||
// TODO is this the most efficient way to accomplish this ?
|
||||
std::mem::swap(&mut callbacks.after_remove, &mut self.after_remove);
|
||||
// TODO verify that this is correct
|
||||
// TODO is this the most efficient way to accomplish this ?
|
||||
std::mem::swap(&mut callbacks.after_remove, &mut self.after_remove);
|
||||
|
||||
for f in self.after_insert.drain(..) {
|
||||
f.0.call(&mut callbacks);
|
||||
for f in self.after_insert.drain(..) {
|
||||
f.0.call(&mut callbacks);
|
||||
}
|
||||
|
||||
// TODO verify that this is correct
|
||||
self.after_insert = vec![];
|
||||
|
||||
// TODO figure out a better way of verifying this
|
||||
assert_eq!(callbacks.after_insert.len(), 0);
|
||||
|
||||
// TODO verify that this is correct
|
||||
// TODO what if `callbacks` is leaked ?
|
||||
std::mem::swap(&mut callbacks.after_remove, &mut self.after_remove);
|
||||
}
|
||||
|
||||
// TODO verify that this is correct
|
||||
self.after_insert = vec![];
|
||||
|
||||
// TODO figure out a better way of verifying this
|
||||
assert_eq!(callbacks.after_insert.len(), 0);
|
||||
|
||||
// TODO verify that this is correct
|
||||
// TODO what if `callbacks` is leaked ?
|
||||
std::mem::swap(&mut callbacks.after_remove, &mut self.after_remove);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -14,6 +14,7 @@ use wasm_bindgen_futures::futures_0_3::spawn_local;
|
|||
use crate::dom_operations;
|
||||
use crate::dom::Dom;
|
||||
use crate::callbacks::Callbacks;
|
||||
use crate::utils::document;
|
||||
|
||||
|
||||
#[inline]
|
||||
|
@ -83,6 +84,7 @@ pub fn insert_children_signal<A, B, C>(element: &A, callbacks: &mut Callbacks, s
|
|||
#[inline]
|
||||
pub(crate) fn insert_children_iter<'a, A: IntoIterator<Item = &'a mut Dom>>(element: &Node, callbacks: &mut Callbacks, value: A) {
|
||||
for dom in value.into_iter() {
|
||||
// TODO can this be made more efficient ?
|
||||
callbacks.after_insert.append(&mut dom.callbacks.after_insert);
|
||||
callbacks.after_remove.append(&mut dom.callbacks.after_remove);
|
||||
|
||||
|
@ -139,15 +141,21 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
|
|||
|
||||
state.children = values;
|
||||
|
||||
let is_inserted = state.is_inserted;
|
||||
let fragment = document().create_document_fragment();
|
||||
|
||||
// TODO use document fragment ?
|
||||
for dom in state.children.iter_mut() {
|
||||
// TODO does this allocate if the filtered Vec is empty ?
|
||||
let after_inserts = state.children.iter_mut().filter(|dom| {
|
||||
dom.callbacks.leak();
|
||||
|
||||
element.append_child(&dom.element).unwrap_throw();
|
||||
fragment.append_child(&dom.element).unwrap_throw();
|
||||
|
||||
if is_inserted {
|
||||
!dom.callbacks.after_insert.is_empty()
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
element.append_child(&fragment).unwrap_throw();
|
||||
|
||||
if state.is_inserted {
|
||||
for dom in after_inserts {
|
||||
dom.callbacks.trigger_after_insert();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue