74 lines
2.3 KiB
JavaScript
74 lines
2.3 KiB
JavaScript
import { component, pure } from 'riot'
|
|
import { cleanNode } from '@riotjs/util/dom'
|
|
|
|
// this object will contain all the components implementations lazy loaded
|
|
const cache = new WeakMap()
|
|
|
|
// expose the cache as static property
|
|
lazy.cache = cache
|
|
|
|
// static attribute in case we want to just export a lazy riot component
|
|
lazy.export = function lazyExport(Loader, Component) {
|
|
// it could be that the user don't want to use a loader for whatever reason
|
|
const hasLoader = Loader && Component
|
|
const LazyComponent = hasLoader ? Component : Loader
|
|
const load = () => typeof LazyComponent === 'function' ? LazyComponent() : Promise.resolve(LazyComponent)
|
|
const cachedComponent = cache.get(LazyComponent)
|
|
|
|
return pure(({ slots, attributes, props }) => ({
|
|
mount(el, parentScope) {
|
|
this.el = el
|
|
this.isMounted = true
|
|
const mount = () => {
|
|
this.mountLazyComponent(parentScope)
|
|
this.el.dispatchEvent(new Event('load'))
|
|
}
|
|
|
|
if (cachedComponent) {
|
|
mount()
|
|
} else {
|
|
if (hasLoader) this.createManagedComponent(Loader, parentScope)
|
|
|
|
load().then(data => {
|
|
cache.set(LazyComponent, data.default || data)
|
|
mount()
|
|
})
|
|
}
|
|
},
|
|
createManagedComponent(Child, parentScope) {
|
|
this.component = component(Child)(this.el, props, {
|
|
attributes, slots, parentScope
|
|
})
|
|
},
|
|
mountLazyComponent(parentScope) {
|
|
// if this component was unmounted just return here
|
|
if (!this.isMounted) return
|
|
|
|
// unmount the loader if it was previously created
|
|
if (this.component) {
|
|
// unmount the bindings (keeping the root node)
|
|
this.component.unmount(true)
|
|
// clean the DOM
|
|
if (this.el.children.length) cleanNode(this.el)
|
|
}
|
|
|
|
// replace the old component instance with the new lazy loaded component
|
|
this.createManagedComponent(cache.get(LazyComponent), parentScope)
|
|
},
|
|
update(parentScope) {
|
|
if (this.isMounted && this.component) this.component.update({}, parentScope)
|
|
},
|
|
unmount(...args) {
|
|
this.isMounted = false
|
|
|
|
if (this.component) this.component.unmount(...args)
|
|
}
|
|
}))
|
|
}
|
|
|
|
export default function lazy(Loader, Component) {
|
|
return {
|
|
name: 'lazy',
|
|
exports: lazy.export(Loader, Component)
|
|
}
|
|
} |