How to remove nodes from the Render Tree?
Asked Answered
B

1

18

I feel like I'm missing something obvious, but how do I remove nodes from the render tree and destroy them correctly?

It looks like I can just do something like mainCtx._node._child.splice(2,1), but this doesn't work in all cases (Scrollviews seem to stick around), and assume there's something relevant in the API but I can't seem to find it.

Braynard answered 15/4, 2014 at 15:20 Comment(0)
B
26

You never remove renderNodes - you use smart RenderNodes to manipulate what is rendered.

The solution depends on what you want to accomplish:

1) I want to manipulate the layout

The easiest way to show / hide / swap parts of the RenderTree is to use a RenderController. You can even specify in/out transitions

var renderController = new RenderController();
renderController.show( .... );
renderController.hide( .... );

See the official example

2) I want to manage performance (and remove stuff I don't need)

Don't worry about removing nodes. Famo.us will manage this for you.

If you want to take control of rendered nodes, write a custom View with a render function. The Flipper class is a simple example (and the RenderController is a complex example of this pattern)

In depth explanation:

  1. Every RenderNode has a render function which creates a renderSpec.
  2. The renderSpec contains information about a Modifier or Surface.
    • The Modifier specs are used to calculate the final CSS properties.
    • The Surface specs are coupled to DOM elements.
  3. Every tick of the Engine, the renderSpec is rendered using the RenderNode.commit function.
  4. The commit function uses the ElementAllocator (from the Context) to allocate/deallocate DOM elements. (Which actually recycles DOM nodes to conserve memory)

Therefore: Just return the correct renderSpec in your custom View, and famo.us will manage memory and performance for you.

BTW, you don't need to use the View class - an object with a render function will suffice. The View class simply adds events and options which is a nice way to create encapsulated, reusable components.

Update: Ready-made Solutions

ShowModifier (gist) a simple modifier to show/hide parts of the rendering tree

 var mod = new ShowModifier({visible:true});
 mod.visible = true;
 mod.show();
 mod.hide();

or, as alternative, use this gist to add visibility functions to Modifier and StateModifier

 modifier.visibleFrom(function(){ return true; }) // function, getter object or value
 stateModifier.setVisible(true); // or false

WARNING: Adding/removing DOM-nodes by manipulating the renderspec might cause a performance penalty!

Brutus answered 16/4, 2014 at 9:53 Comment(4)
Awesome! Yeah, my goals were a combination of both of these. Thanks for the detailed explanation, particularly the in depth part :)Braynard
None of the above works correctly if you use z-indexes, it starts to mess after a while, it seems that the only way to do this is to append only to the DOM, which is clearly a faulty modelRedness
The problem is that things like Surfaces get stored into Entity when Entity.register is called. They don't get removed automatically, so if you have an app that creates new Surfaces over time, you'll have a memory leak. The new Mixed Mode will have a solution for this I've been told. That's where the real problem lies.Featherstone
@Braynard ^ Entity.register is called in ElementOutput. Can't wait for Mixed Mode so we can easily remove things from a RenderTree.Featherstone

© 2022 - 2024 — McMap. All rights reserved.