perf($compile): don't register $destroy callbacks on element-transcluded nodes

This is a major perf win in the large table benchmark (~100ms or 9).

This cleanup is needed only for regular transclusion because only then the DOM hierarchy doesn't match scope hierarchy
(transcluded scope is a child of the parent scope and not a child of the isolate scope)

We should consider refactoring this further for the case of regular transclusion
and consider using scope events instead.
This commit is contained in:
Igor Minar
2014-08-12 17:00:50 -07:00
parent d05f27e274
commit b5f7970be5
2 changed files with 9 additions and 6 deletions

View File

@@ -1000,7 +1000,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
if ( nodeLinkFn.transcludeOnThisElement ) {
childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
childBoundTranscludeFn = createBoundTranscludeFn(
scope, nodeLinkFn.transclude, parentBoundTranscludeFn,
nodeLinkFn.elementTranscludeOnThisElement);
} else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
childBoundTranscludeFn = parentBoundTranscludeFn;
@@ -1021,7 +1023,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
}
function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) {
var boundTranscludeFn = function(transcludedScope, cloneFn, controllers) {
var scopeCreated = false;
@@ -1033,7 +1035,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
var clone = transcludeFn(transcludedScope, cloneFn, controllers, previousBoundTranscludeFn);
if (scopeCreated) {
if (scopeCreated && !elementTransclusion) {
clone.on('$destroy', function() { transcludedScope.$destroy(); });
}
return clone;
@@ -1410,6 +1412,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective;
nodeLinkFn.templateOnThisElement = hasTemplate;
nodeLinkFn.transclude = childTranscludeFn;

View File

@@ -4128,7 +4128,7 @@ describe('$compile', function() {
function testCleanup() {
var privateData, firstRepeatedElem;
element = $compile('<div><div ng-repeat="x in xs">{{x}}</div></div>')($rootScope);
element = $compile('<div><div ng-repeat="x in xs" ng-click="noop()">{{x}}</div></div>')($rootScope);
$rootScope.$apply('xs = [' + xs + ']');
firstRepeatedElem = element.children('.ng-scope').eq(0);
@@ -4136,8 +4136,8 @@ describe('$compile', function() {
expect(firstRepeatedElem.data('$scope')).toBeDefined();
privateData = jQuery._data(firstRepeatedElem[0]);
expect(privateData.events).toBeDefined();
expect(privateData.events.$destroy).toBeDefined();
expect(privateData.events.$destroy[0]).toBeDefined();
expect(privateData.events.click).toBeDefined();
expect(privateData.events.click[0]).toBeDefined();
$rootScope.$apply('xs = null');