perf(ngAnimate): avoid repeated calls to addClass/removeClass when an…#16613
perf(ngAnimate): avoid repeated calls to addClass/removeClass when an…#16613Narretz wants to merge 1 commit intoangular:masterfrom
Conversation
|
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
1 similar comment
|
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
gkalpak
left a comment
There was a problem hiding this comment.
I won't pretend to understand everything that's going on, but looks reasonable (and there are tests that test stuff 😁)
| this.$get = [function() { | ||
| return { | ||
| cacheKey: function(node, method, addClass, removeClass) { | ||
| var parentNode = node.parentNode; |
There was a problem hiding this comment.
Isn't it possible for node.parentNode to be undefined?
There was a problem hiding this comment.
Good question! You cannot animate elements that are not attached to the document / rootElement, and even an html element has a parentNode, so with this in mind, it's fine.
src/ngAnimate/shared.js
Outdated
| if (classes.length) { | ||
| options.preparationClasses = classes; | ||
| element.addClass(classes); | ||
| $$jqLite.addClass(element, classes); |
| return entry && entry.value; | ||
| }, | ||
|
|
||
| put: function(key, value, isValid) { |
There was a problem hiding this comment.
What happens when you can put multiple times for the same key with different isValid values?
Why isn't isValid updated?
There was a problem hiding this comment.
I don't think a different isValid value is possible for the same cacheKey in one and the same animation run. The cacheKey is based on the classes on the element, and the classes define if there's an animation with duration on the element. Since a cacheKey is unique per class combination, it should not be possible to have different validity per cacheKey.
src/ngAnimate/animateCss.js
Outdated
|
|
||
| // if a css animation has no duration we | ||
| // should mark that so that repeated addClass/removeClass calls are skipped | ||
| var hasNoDuration = allowNoDuration || (timings.transitionDuration > 0 || timings.animationDuration > 0); |
There was a problem hiding this comment.
Shouldn't this be named hasDuration?
src/ngAnimate/animateCss.js
Outdated
| if (flags.recalculateTimingStyles) { | ||
| fullClassName = node.getAttribute('class') + ' ' + preparationClasses; | ||
| cacheKey = gcsHashFn(node, fullClassName); | ||
| fullClassName = node.className + ' ' + preparationClasses; |
There was a problem hiding this comment.
classNamecan also be an instance ofSVGElementif the element is anSVGAnimatedString. It is better to get/set theclassNameof an element usingElement.getAttributeandElement.setAttributeif you are dealing with SVG elements.
src/ngAnimate/animation.js
Outdated
| finalAnimations[i][j] = entry.fn; | ||
|
|
||
| // the first row of elements shouldn't have a prepare-class added to them | ||
| // since the elements are at the top of the animation hierarcy and they |
| if (removeClass) { | ||
| parts.push(removeClass); | ||
| } | ||
| return parts.join(' '); |
There was a problem hiding this comment.
Is it a concerns that adding/removing the same class can result in the same key?
E.g. cacheKey(node, merhod, 'foo') === cacheKey(node, method, null, 'foo').
There was a problem hiding this comment.
If you try to remove a class, the cacheKey will contain the class to remove twice: once because the class is on the element, once for removeClass.
Since the animate functions bail out early when you try to remove a class that doesn't exist on the element, it's not possible that the key for addClass is the same as for removeClass.
| this.$get = [function() { | ||
| return { | ||
| cacheKey: function(node, method, addClass, removeClass) { | ||
| var parentNode = node.parentNode; |
There was a problem hiding this comment.
Good question! You cannot animate elements that are not attached to the document / rootElement, and even an html element has a parentNode, so with this in mind, it's fine.
| if (removeClass) { | ||
| parts.push(removeClass); | ||
| } | ||
| return parts.join(' '); |
There was a problem hiding this comment.
If you try to remove a class, the cacheKey will contain the class to remove twice: once because the class is on the element, once for removeClass.
Since the animate functions bail out early when you try to remove a class that doesn't exist on the element, it's not possible that the key for addClass is the same as for removeClass.
| return entry && entry.value; | ||
| }, | ||
|
|
||
| put: function(key, value, isValid) { |
There was a problem hiding this comment.
I don't think a different isValid value is possible for the same cacheKey in one and the same animation run. The cacheKey is based on the classes on the element, and the classes define if there's an animation with duration on the element. Since a cacheKey is unique per class combination, it should not be possible to have different validity per cacheKey.
test/ngAnimate/animateCacheSpec.js
Outdated
| var validEntry = { someEssentialProperty: true }; | ||
| var invalidEntry = { someEssentialProperty: false }; | ||
| describe('containsCachedAnimationWithoutDuration', function() { | ||
| it('should return false if the validity of an key is false', inject(function($$animateCache) { |
bc5c234 to
b13a6fa
Compare
…imation has no duration Background: ngAnimate writes helper classes to DOM elements to see if animations are defined on them. If many elements have the same definition, we can cache the definition and skip the application of the helper classes altogether. This helps particularly with large ngRepeat collections. Closes angular#14165 Closes angular#14166
b13a6fa to
9463045
Compare
…imation has no duration Background: ngAnimate writes helper classes to DOM elements to see if animations are defined on them. If many elements have the same definition, and the same parent, we can cache the definition and skip the application of the helper classes altogether. This helps particularly with large ngRepeat collections. Closes #14165 Closes #14166 Closes #16613
…imation has no duration
Background:
ngAnimate writes helper classes to DOM elements to see if animations are defined on them. If many
elements have the same definition, we can cache the definition and skip the application of the
helper classes altogether. This helps particularly with large ngRepeat collections.
Closes #14165
Closes #14166
What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
What is the current behavior? (You can also link to an open issue here)
What is the new behavior (if this is a feature change)?
Does this PR introduce a breaking change?
Please check if the PR fulfills these requirements
Other information: