-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(material/button): make button ripples lazy #26568
Conversation
127faf5
to
89ee76f
Compare
6f12cda
to
6b2cbec
Compare
d6b4ec3
to
71841bc
Compare
9b96733
to
3d72aca
Compare
Here is the design doc which describes this feature as well as the rationale for why it was written this way: |
* Traverses the element and its parents (heading toward the document root) | ||
* until it finds a mat-button that has not been initialized. | ||
*/ | ||
private _closest(element: Element): Element | null { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use the native Element.closest
API here instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mleibman could probably speak to this best but from what I remember in our last discussions, this is actually a performance improvement. I have added a link to their example at the bottom of our design doc
https://docs.google.com/document/d/13paaXem1sXg6462-bb05M8GHguvQcsXGC8FxDeK6w_Q/edit?usp=sharing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's not exactly the same, because it's setting a symbol on the DOM node whereas here we have an attribute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm very skeptical that a userspace closest
is faster than the browser native closest
. I would need to see some compelling evidence, and then I would go complain to Chrome.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds plausible - I could have just misremembered. I switched to using the native Element.closest
and I can revisit this if it really is a performance bottleneck
* Traverses the element and its parents (heading toward the document root) | ||
* until it finds a mat-button that has not been initialized. | ||
*/ | ||
private _closest(element: Element): Element | null { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm very skeptical that a userspace closest
is faster than the browser native closest
. I would need to see some compelling evidence, and then I would go complain to Chrome.
src/material/button/button-ripple.ts
Outdated
constructor( | ||
_elementRef: ElementRef<HTMLElement>, | ||
readonly ngZone: NgZone, | ||
readonly platform: Platform, | ||
@Optional() @Inject(MAT_RIPPLE_GLOBAL_OPTIONS) globalOptions?: RippleGlobalOptions, | ||
@Optional() @Inject(ANIMATION_MODULE_TYPE) _animationMode?: string, | ||
@Optional() @Inject(DOCUMENT) document?: Document, | ||
) { | ||
super(_elementRef, ngZone, platform, globalOptions, _animationMode, document); | ||
this._buttonEl = _elementRef.nativeElement; | ||
this._buttonEl.classList.remove('mat-ripple'); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer the inject
function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was able to do this for document
, but not any of the other symbols because they are referenced in the call to super
and references to this
are not allowed before super
is called
54ba026
to
fc7f0a8
Compare
@wagnermaciel it doesn't actually have to be a directive instance, it just has to have the same API shape, no? rough pseudo-code for the idea type PublicInterface<T> = {[K in keyof T]: T[K]};
class DeferredRipple implements PublicInterface<MatRipple> {
// ripple stuff
}
class MatButton {
get ripple(): MatRipple {
if (!this._rippleInternal) this._rippleInternal = this.createRipple();
return this._rippleInternal;
}
private _rippleInternal = null;
} (it's possible I'm missing some detail, admittedly) |
@jelbourn Previously, when I considered this approach I was against it because I didn't want to be creating & having to maintain a MatRipple-like object. This time around, I just tried creating a |
b253a9a
to
369e74e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good- the only main thing left is adding additional tests for MatButtonLazyLoader
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
22df8c7
to
24757b4
Compare
24757b4
to
f4a22d4
Compare
Hi @wagnermaciel @jelbourn, |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
No description provided.