Skip to content

Commit

Permalink
Improve performance of named templates by caching the parsed nodes so…
Browse files Browse the repository at this point in the history
… they can be used for future rendering by using cloneNode. This will only help if a template is used more than once, especially with `foreach`.
  • Loading branch information
mbest committed Dec 9, 2016
1 parent ac30244 commit 4e0a4c4
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 6 deletions.
2 changes: 1 addition & 1 deletion spec/nativeTemplateEngineBehaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ describe('Native template engine', function() {

it('can fetch template from <textarea> elements and data-bind on results', function () {
var testTextAreaTemplate = ensureNodeExistsAndIsEmpty("testTextAreaTemplate", "textarea"),
prop = (typeof testTextAreaTemplate.innerText !== "undefined") ? "innerText" : "textContent";
prop = "value";
testRenderTemplate(testTextAreaTemplate, "testTextAreaTemplate", prop);
});

Expand Down
21 changes: 16 additions & 5 deletions src/templating/templateSources.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,22 @@
var element = this.domElement;
if (arguments.length == 0) {
var templateData = getTemplateDomData(element),
containerData = templateData.containerData;
return containerData || (
this.templateType === templateTemplate ? element.content :
this.templateType === templateElement ? element :
undefined);
nodes = templateData.containerData || (
this.templateType === templateTemplate ? element.content :
this.templateType === templateElement ? element :
undefined);
if (!nodes || templateData.alwaysCheckText) {
// If the template is associated with an element that stores the template as text,
// parse and cache the nodes whenever there's new text content available. This allows
// the user to update the template content by updating the text of template node.
var text = this['text']();
if (text) {
nodes = ko.utils.parseHtmlForTemplateNodes(text, element.ownerDocument);
this['text'](""); // clear the text from the node
setTemplateDomData(element, {containerData: nodes, alwaysCheckText: true});
}
}
return nodes;
} else {
var valueToWrite = arguments[0];
setTemplateDomData(element, {containerData: valueToWrite});
Expand Down
5 changes: 5 additions & 0 deletions src/utils.domManipulation.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@
simpleHtmlParse(html, documentContext); // ... otherwise, this simple logic will do in most common cases.
};

ko.utils.parseHtmlForTemplateNodes = function(html, documentContext) {
var nodes = ko.utils.parseHtmlFragment(html, documentContext);
return (nodes.length && nodes[0].parentElement) || ko.utils.moveCleanedNodesToContainerElement(nodes);
};

ko.utils.setHtml = function(node, html) {
ko.utils.emptyDomNode(node);

Expand Down

0 comments on commit 4e0a4c4

Please sign in to comment.