In this series, How lit-html works, I will explore (not explain) internal implementation of lit-html.
In the last 4 posts, we saw what TemplateResult and SVGTemplateResult looks like.
From now on, I will explore the render function.
  
  
  render function
render function is defined beside a variable whose name is parts.
export const parts = new WeakMap<Node, NodePart>();
export const render =
    (result: unknown,
     container: Element|DocumentFragment,
     options?: Partial<RenderOptions>) => {
      let part = parts.get(container);
      if (part === undefined) {
        removeNodes(container, container.firstChild);
        parts.set(
            container,
            part = new NodePart(
                {
                  templateFactory,
                  ...options,
                },
                undefined));
        part.appendInto(container);
      }
      part.setValue(result);
      part.commit();
    };
This function receives two arguments. First one is an instance of TemplateResult or SVGTemplateResult. Second is the container, which is a DOM parent inside which the content is rendered.
Searching Cache
Firstly, render function checks if an instance of NodePart class is stored in parts with the container as a key.
  
  
  Create a New NodePart
If a cached NodePart instance is not found, then all the direct children of the container are removed by removeNodes function.
export const removeNodes =
    (container: Node, start: Node|null, end: Node|null = null): void => {
      while (start !== end) {
        const n = start!.nextSibling;
        container.removeChild(start!);
        start = n;
      }
    };
The algorithm is quite similar to reparentNodes function that I saw in the last post. Only difference is how the functions manipulate DOM tree.
After cleaning up the container, a new NodePart instance is registered into the parts and is associated with with the container.
Rendering
Finally, render function lets the NodePart instance call three methods of it, but I will explore this part in later posts. Instead, I will recap what WeakMap is, because it's worth using in other development as well.
WeakMap
MDN says that the WeakMap object is a collection of key/value pairs and the keys must be objects.
The word "weak" here means that the reference from weak map to the key object doesn't prevent the object from being garbage collected.
Thus, it is really convenient to store data in a WeakMap as a cache. We don't have to check, every time we do something or periodically the data of the object, whether the data is no longer used.
Just for information, there are also Map, Set, WeakSet, each of which has suitable situation.
Summary
So far, I learned the following points:
- 
renderfunction caches NodePart. - 
renderfunction creates a new NodePart if no corresponding cache is found. - 
renderfunction delegates actual rendering process to the NodePart instance. 
From the next post, I will dive into the NodePart class.
    
Top comments (0)