- From: James Browning <notifications@github.com>
- Date: Sun, 24 Mar 2019 18:30:45 -0700
- To: w3c/webcomponents <webcomponents@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <w3c/webcomponents/issues/704/476025026@github.com>
@dmitriid Neither template instantiation or `lit-html` use `.innerHTML` to update the DOM. This seems to be some FUD around how template instantiation works but template instantiation and `lit-html` actually work *more* efficiently than a virtual DOM by holding references to part of the DOM that have template parts. In `lit-html`'s case, it *only* creates the initial template using `.innerHTML`, to actually update the DOM it [inserts nodes directly into the correct location (and similar for attributes)](https://github.com/Polymer/lit-html/blob/master/src/lib/parts.ts#L203). For example consider this template: ```html <template id="exampleTemplate"> <span title="{{foo}}">This is a sample {{bar}} with instantiation</span> <span>Also {{foo}}</span> </template> ``` when we create an instance of the template a set of references are created to the elements that have that name: ``` { foo: [ AttributeTemplatePart { el: /* ref to <span title="{{foo}}"> element */ attrName: 'title', }, NodeTemplatePart { previousNode: /* The previous text node before {{foo}}: "Also" */ nextNode: /* The text node after {{foo}} */ }, ], bar: [ NodeTemplatePart { previousNode: /* The previous text node before {{bar}}: "This is a sample " */ nextNode: /* The next text node after {{bar}}: " with instantiation" } ], } ``` now when we call something like `instance.update({ foo: 'banana', bar: 'cabbage' })` all `.update` needs to do is something like this: ```js function update(data) { for (const [key, value] of Object.entries(data)) { for (const templatePart of this._templateParts[key]) { templatePart.update(value) } this._templateParts[key].update(value) } } ``` this is *way more efficient* than maintaining a virtual copy of the DOM as we simply implement `AttributeTemplatePart` and `NodeTemplatePart` so that they go directly to their location in the DOM and update the value. e.g. `NodeTemplatePart` could be implemented like this: ```js class NodeTemplatePart { constructor(previousNode, nextNode) { this._previousNode = previousNode this._nextNode = nextNode } // This is overly simplified and assumes there's a node both before and after // the {{curlies}}, a real implementation would hold a reference to the parent element // as well and if there's no previousNode/nextNode it'd just replace the whole contents update(values) { if (typeof values === 'string') { values = [new Text(values)] } while (this._previousNode.nextNode !== this._nextNode) { this._previousNode.nextNode.remove() } for (const value of values) { this._nextNode.parentNode.insertBefore(value, this._nextNode) } } } ``` -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/w3c/webcomponents/issues/704#issuecomment-476025026
Received on Monday, 25 March 2019 01:31:07 UTC