UNPKG

@v4fire/client

Version:

V4Fire client core library

139 lines (108 loc) 3.48 kB
/*! * V4Fire Client Core * https://github.com/V4Fire/Client * * Released under the MIT license * https://github.com/V4Fire/Client/blob/master/LICENSE */ import { identity } from 'core/functools'; import * as c from 'core/component/const'; import { createMeta, fillMeta, attachTemplatesToMeta } from 'core/component/meta'; import { getInfoFromConstructor } from 'core/component/reflection'; import { getComponent, ComponentEngine } from 'core/component/engines'; import { registerParentComponents } from 'core/component/register/helpers'; import type { ComponentOptions } from 'core/component/interface'; /** * Registers a new component * * @decorator * @param [opts] - additional options * * @example * ```js * @component() * class Button { * * } * ``` */ export function component(opts?: ComponentOptions): Function { return (target) => { const componentInfo = getInfoFromConstructor(target, opts), componentParams = componentInfo.params; c.initEmitter .emit('bindConstructor', componentInfo.name); if (!Object.isTruly(componentInfo.name) || componentParams.root || componentInfo.isAbstract) { regComponent(); } else { const initList = c.componentInitializers[componentInfo.name] ?? []; c.componentInitializers[componentInfo.name] = initList; initList.push(regComponent); } // If we have a smart component, // we need to compile 2 components in the runtime if (Object.isPlainObject(componentParams.functional)) { component({ ...opts, name: `${componentInfo.name}-functional`, functional: true })(target); } function regComponent(): void { // Lazy initializing of parent components registerParentComponents(componentInfo); const {parentMeta} = componentInfo; const meta = createMeta(componentInfo), componentName = componentInfo.name; if (componentInfo.params.name == null || !componentInfo.isSmart) { c.components.set(target, meta); } c.components.set(componentName, meta); c.initEmitter.emit(`constructor.${componentName}`, {meta, parentMeta}); if (componentInfo.isAbstract || meta.params.functional === true) { fillMeta(meta, target); if (!componentInfo.isAbstract) { loadTemplate(meta.component)(identity); } } else if (meta.params.root) { c.rootComponents[componentName] = new Promise(loadTemplate(getComponent(meta))); } else { const c = ComponentEngine.component(componentName, loadTemplate(getComponent(meta), true)(identity)); if (Object.isPromise(c)) { c.catch(stderr); } } // Function that waits till a component template is loaded function loadTemplate(component: object, lazy: boolean = false): (resolve: Function) => any { return promiseCb; function promiseCb(resolve: Function) { if (meta.params.tpl === false) { return attachTemplatesAndResolve(); } return waitComponentTemplates(); function waitComponentTemplates() { const fns = TPLS[meta.componentName]; if (fns) { return attachTemplatesAndResolve(fns); } if (lazy) { return promiseCb; } requestIdleCallback(waitComponentTemplates, {timeout: 50}); } function attachTemplatesAndResolve(tpls?: Dictionary) { attachTemplatesToMeta(meta, tpls); // @ts-ignore (access) component.staticRenderFns = meta.component.staticRenderFns; return resolve(component); } } } } }; }