Last active
March 14, 2018 20:27
-
-
Save andrejewski/ce3c2cb71af10b9c99bc1a0f535aa17e to your computer and use it in GitHub Desktop.
Declaratively defer rendering for large components and lists (Can v2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Map from 'can/map/'; | |
import Component from 'can/component/'; | |
const viewModel = Map.extend('CanDeferVM', { | |
define: { | |
delayMs: { | |
value: 0, | |
set: x => parseInt(x, 10) | |
}, | |
initialHtml: { value: null }, | |
/* | |
This is a convenience prop for rendering lists in | |
chucks as one can pass (delay-scalar)="@index" | |
and the pieces will be loaded gradually. | |
*/ | |
delayScalar: { | |
value: null, | |
set: x => parseInt(x, 10) | |
}, | |
isActive: { value: false }, | |
delay: { | |
get () { | |
const delayScalar = this.attr('delayScalar'); | |
if (typeof delayScalar !== 'number') { | |
return this.attr('delayMs'); | |
} | |
return delayScalar * this.attr('delayMs'); | |
} | |
} | |
}, | |
activate () { | |
const isActive = this.attr('isActive'); | |
const isActivating = !!(this._timeout || this._request); | |
const shouldActivate = !(isActive || isActivating); | |
if (shouldActivate) { | |
this._timeout = setTimeout(() => { | |
this._request = requestAnimationFrame(() => { | |
this.attr('isActive', true); | |
this._timeout = null; | |
this._request = null; | |
}); | |
}, this.attr('delay')); | |
} | |
}, | |
cancel () { | |
if (this._timeout) { | |
clearTimeout(this._timeout); | |
this._timeout = null; | |
} | |
if (this._request) { | |
cancelAnimationFrame(this._request); | |
this._request = null; | |
} | |
} | |
}); | |
export default Component.extend('CanDeferComponent', { | |
tag: 'can-defer', | |
viewModel, | |
template: '{{#if isActive}}<content/>{{else}}{{{initialHtml}}}{{/if}}', | |
leakScope: false, | |
events: { | |
inserted () { | |
this.viewModel.activate(); | |
}, | |
removed () { | |
this.viewModel.cancel(); | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment