UNPKG

@v4fire/client

Version:

V4Fire client core library

158 lines (126 loc) 4.02 kB
/*! * V4Fire Client Core * https://github.com/V4Fire/Client * * Released under the MIT license * https://github.com/V4Fire/Client/blob/master/LICENSE */ import * as init from 'core/component/construct'; import { forkMeta } from 'core/component/meta'; import { initProps } from 'core/component/prop'; import type { RenderContext } from 'core/component/render'; import type { CreateElement } from 'core/component/engines'; import { $$, componentOpts } from 'core/component/functional/const'; import { destroyComponent } from 'core/component/functional/helpers'; import type { FunctionalCtx } from 'core/component/interface'; import type { CreateFakeCtxOptions } from 'core/component/functional/interface'; export * from 'core/component/functional/interface'; /** * Creates the fake context for a functional component is based on the specified parameters * * @param createElement - function to create VNode element * @param renderCtx - render context from VNode * @param baseCtx - component context that provided the core functionality * @param [opts] - additional options */ export function createFakeCtx<T extends object = FunctionalCtx>( createElement: CreateElement, renderCtx: Partial<RenderContext>, baseCtx: FunctionalCtx, opts: CreateFakeCtxOptions ): T { const fakeCtx = Object.create(baseCtx), meta = forkMeta(fakeCtx.meta); const {component} = meta, {parent, children, data: dataOpts} = renderCtx; let $options; if (parent?.$options) { const { filters = {}, directives = {}, components = {} } = parent.$options; $options = { filters: Object.create(filters), directives: Object.create(directives), components: Object.create(components) }; } else { $options = { filters: {}, directives: {}, components: {} }; } if (Object.isDictionary(component)) { Object.assign($options, Object.reject(component, componentOpts)); Object.assign($options.filters, component.filters); Object.assign($options.directives, component.directives); Object.assign($options.components, component.components); } if (renderCtx.$options) { const o = renderCtx.$options; Object.assign($options, Object.reject(o, componentOpts)); Object.assign($options.filters, o.filters); Object.assign($options.directives, o.directives); Object.assign($options.components, o.components); } fakeCtx.unsafe = fakeCtx; fakeCtx.children = Object.isArray(children) ? children : []; fakeCtx.$parent = parent; fakeCtx.$root = renderCtx.$root ?? parent?.$root ?? fakeCtx; fakeCtx.$renderEngine = fakeCtx.$root.$renderEngine; fakeCtx.$options = $options; fakeCtx.$props = renderCtx.props ?? {}; fakeCtx.$attrs = dataOpts?.attrs ?? {}; fakeCtx.$listeners = renderCtx.listeners ?? dataOpts?.on ?? {}; fakeCtx.$refs = {}; fakeCtx.$slots = { default: Object.size(children) > 0 ? children : undefined, ...renderCtx.slots?.() }; fakeCtx.$scopedSlots = { ...Object.isFunction(renderCtx.scopedSlots) ? renderCtx.scopedSlots() : renderCtx.scopedSlots }; fakeCtx.$createElement = createElement.bind(fakeCtx); fakeCtx.$destroy = () => destroyComponent(fakeCtx); fakeCtx._self = fakeCtx; fakeCtx._renderProxy = fakeCtx; fakeCtx._c = fakeCtx.$createElement; fakeCtx._staticTrees = []; fakeCtx.$nextTick = (cb?: Function) => { const {$async: $a} = fakeCtx; if (cb) { $a.setImmediate(cb); return; } return $a.nextTick(); }; fakeCtx.$forceUpdate = () => { // eslint-disable-next-line @typescript-eslint/unbound-method if (!Object.isFunction(parent?.$forceUpdate)) { return; } fakeCtx.$async.setImmediate(() => parent!.$forceUpdate(), { label: $$.forceUpdate }); }; if (fakeCtx.$root == null) { fakeCtx.$root = fakeCtx; } initProps(fakeCtx, { from: renderCtx.props, store: fakeCtx, saveToStore: opts.initProps }); init.beforeCreateState(fakeCtx, meta, { addMethods: true, implementEventAPI: true }); init.beforeDataCreateState(fakeCtx, {tieFields: true}); return fakeCtx; }