diff options
| author | Michał Gołębiowski | 2013-10-16 15:15:21 +0200 | 
|---|---|---|
| committer | Igor Minar | 2013-12-13 02:07:11 -0800 | 
| commit | 3410f65e790a81d457b4f4601a1e760a6f8ede5e (patch) | |
| tree | 2f37146f1399d23ea02de44e8209879eda949e1f /src | |
| parent | f3de5b6eac90baf649506072162f36dbc6d2f028 (diff) | |
| download | angular.js-3410f65e790a81d457b4f4601a1e760a6f8ede5e.tar.bz2 | |
perf(jqLite): implement and use the `empty` method in place of `html(‘’)`
jQuery's elem.html('') is way slower than elem.empty(). As clearing
element contents happens quite often in certain scenarios, switching
to using .empty() provides a significant performance boost when using
Angular with jQuery.
Closes #4457
Diffstat (limited to 'src')
| -rw-r--r-- | src/Angular.js | 2 | ||||
| -rw-r--r-- | src/jqLite.js | 22 | ||||
| -rw-r--r-- | src/ng/compile.js | 4 | ||||
| -rw-r--r-- | src/ng/directive/ngTransclude.js | 2 | ||||
| -rw-r--r-- | src/ng/directive/select.js | 4 | ||||
| -rw-r--r-- | src/ngAnimate/animate.js | 2 | 
6 files changed, 25 insertions, 11 deletions
| diff --git a/src/Angular.js b/src/Angular.js index b09d3a7f..e32c3739 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -974,7 +974,7 @@ function startingTag(element) {    try {      // turns out IE does not let you set .html() on elements which      // are not allowed to have children. So we just ignore it. -    element.html(''); +    element.empty();    } catch(e) {}    // As Per DOM Standards    var TEXT_NODE = 3; diff --git a/src/jqLite.js b/src/jqLite.js index e7531fb3..8a45f966 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -46,6 +46,7 @@   * - [`contents()`](http://api.jquery.com/contents/)   * - [`css()`](http://api.jquery.com/css/)   * - [`data()`](http://api.jquery.com/data/) + * - [`empty()`](http://api.jquery.com/empty/)   * - [`eq()`](http://api.jquery.com/eq/)   * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name   * - [`hasClass()`](http://api.jquery.com/hasClass/) @@ -358,6 +359,15 @@ function jqLiteInheritedData(element, name, value) {    }  } +function jqLiteEmpty(element) { +  for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) { +    jqLiteDealoc(childNodes[i]); +  } +  while (element.firstChild) { +    element.removeChild(element.firstChild); +  } +} +  //////////////////////////////////////////  // Functions which are declared directly.  ////////////////////////////////////////// @@ -552,7 +562,9 @@ forEach({        jqLiteDealoc(childNodes[i]);      }      element.innerHTML = value; -  } +  }, + +  empty: jqLiteEmpty  }, function(fn, name){    /**     * Properties: writes return selection, reads return first value @@ -562,11 +574,13 @@ forEach({      // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it      // in a way that survives minification. -    if (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined) { +    // jqLiteEmpty takes no arguments but is a setter. +    if (fn !== jqLiteEmpty && +        (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {        if (isObject(arg1)) {          // we are a write, but the object properties are the key/values -        for(i=0; i < this.length; i++) { +        for (i = 0; i < this.length; i++) {            if (fn === jqLiteData) {              // data() takes the whole object in jQuery              fn(this[i], arg1); @@ -591,7 +605,7 @@ forEach({        }      } else {        // we are a write, so apply to all children -      for(i=0; i < this.length; i++) { +      for (i = 0; i < this.length; i++) {          fn(this[i], arg1, arg2);        }        // return self for chaining diff --git a/src/ng/compile.js b/src/ng/compile.js index a6bcc3e7..0af76a75 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1219,7 +1219,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {                                          });            } else {              $template = jqLite(jqLiteClone(compileNode)).contents(); -            $compileNode.html(''); // clear contents +            $compileNode.empty(); // clear contents              childTranscludeFn = compile($template, transcludeFn);            }          } @@ -1651,7 +1651,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {                ? origAsyncDirective.templateUrl($compileNode, tAttrs)                : origAsyncDirective.templateUrl; -      $compileNode.html(''); +      $compileNode.empty();        $http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).          success(function(content) { diff --git a/src/ng/directive/ngTransclude.js b/src/ng/directive/ngTransclude.js index 490ea21f..8eefb6ff 100644 --- a/src/ng/directive/ngTransclude.js +++ b/src/ng/directive/ngTransclude.js @@ -69,7 +69,7 @@ var ngTranscludeDirective = ngDirective({    link: function($scope, $element, $attrs, controller) {      controller.$transclude(function(clone) { -      $element.html(''); +      $element.empty();        $element.append(clone);      });    } diff --git a/src/ng/directive/select.js b/src/ng/directive/select.js index 86e04242..d87fa5d3 100644 --- a/src/ng/directive/select.js +++ b/src/ng/directive/select.js @@ -333,13 +333,13 @@ var selectDirective = ['$compile', '$parse', function($compile,   $parse) {            // becomes the compilation root            nullOption.removeClass('ng-scope'); -          // we need to remove it before calling selectElement.html('') because otherwise IE will +          // we need to remove it before calling selectElement.empty() because otherwise IE will            // remove the label from the element. wtf?            nullOption.remove();          }          // clear contents, we'll add what's needed based on the model -        selectElement.html(''); +        selectElement.empty();          selectElement.on('change', function() {            scope.$apply(function() { diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js index 8ff7b429..aeb6e32e 100644 --- a/src/ngAnimate/animate.js +++ b/src/ngAnimate/animate.js @@ -1237,7 +1237,7 @@ angular.module('ngAnimate', ['ng'])            //make the element super hidden and override any CSS style values            clone.attr('style','position:absolute; top:-9999px; left:-9999px');            clone.removeAttr('id'); -          clone.html(''); +          clone.empty();            forEach(oldClasses.split(' '), function(klass) {              clone.removeClass(klass); | 
