esl
esl copied to clipboard
[🚀 esl-core]: ability to share debounced resize across ESLEventListeners
As an ESL consumer, I want to be sure that subscriptions to the frequently dispatched event can be optimized at the library level.
Use case:
class MyEl {
@listen({event: 'resize', target: window})
@decorate(debounce, 200)
onResize() {
}
}
Frequent env events (like 'resize') are usually globally optimized by decorating it using debounce
or throttle
.
Current behavior:
Each instance of MyEl and other similar components subscribes to the window.resize
globally and decorates the result callback locally for each instance.
Proposed behavior:
Ability to make a shared denounced target for window.resize
and throttled for window.scroll
Draft solution: make the user able to define custom handlers (hooks)
TODO: POC @ala-n to create a story for POC variation
Pros:
- ... Cons:
- complications of listener
Rust to renew cases are:
- window resize event denounced version (main use case with a shared equal debounce)
- window scroll event throttled version (main use case with a shared equal timeout) Note: that's only cases we faced, but that doesn't mean that we do not need denounced scroll, or no need to have a customizable timeout. Here is a list of API drafts to think:
@listen({
// But how to pass the timeout...
event: 'resize:debounced resize:throttled',
// Lazy getter for WindowEventProxy
target: ESLEventUtils.window
})
@listen({
event: 'resize',
target: ESLEventUtils.debounced(300)(window)
})
@listen({
event: 'resize',
target: ESLEventUtils.throttled(300)(window)
})
@listen({
event: 'resize',
// Resize observer case
target: (that) => ESLEventUtils.resize(that.$el)
})
@listen({
event: 'resize',
// Resize observer case
target: (that) => ESLResizeObserverTarget.create(that.$el)
})
@listen({
event: 'enter leave intersect',
// Hold all utility event targets under ESLEventUtils
target: ESLEventUtils.viewport
})
@listen({
event: 'enter',
// If we need another target thaen current element
target: (that: MyComponent) => ESLEventUtils.viewport(that.$el)
})
@listen({
event: 'leave',
// Have a separate class for event targets
target: ESLEventHelpers.viewport
})
@listen({
event: 'enter',
// Or mb we don't need a "cumulative" class at all ...
target: ESLIntersectionTarget.instance
})
// Window proxy variations (not clear how to deal with element resize)
@listen({
event: 'resize',
target: ESLWindowProxy.resize.debounce(300)
})
@listen({
event: 'scroll',
target: ESLWindowProxy.scroll.throttle(300)
})
We can use them as a basis and chose a good to define the common pricipals
- 2 impl +1 vote from API point of view (??? )
- +1 vote against event aliases
- +1 vote for a totally separate impl for Intersection and ResizeObserv
- +8.5
@listen({
event: 'resize scroll',
target: ESLEventUtils.window.debounced
})
@listen({
event: 'resize scroll',
target: ESLEventUtils.window.throttled
})
@listen({
event: 'enter',
target: ESLEventUtils.intersection
})
@listen({
event: 'resize',
// How to handle edge cases
target: ESLEventUtils.resize
})
- +7.6 ESLEventUtils as an API holder -1.5
- +8.6 Do not care about super custom cases