import { ComponentPropsOptions, defineComponent, ExtractPropTypes, getCurrentInstance, inject, provide, SetupContext } from "vue"; // 表示重写defineComponent 组件 export function customComponent< PropsOptions extends Readonly, Props extends Readonly>, Refer > (options: { name?: string, props?: PropsOptions, provideRefer?: boolean, setup: (props: Props, ctx: SetupContext) => { refer?: Refer, render: () => any } }) { const {setup, provideRefer, ...leftOptions} = options; return { ...defineComponent({ ...leftOptions, setup(props: Props, setupContext: SetupContext) { if (!setup) { console.error("customComponent: setup is required"); return () => null } const ctx = getCurrentInstance() as any; const {refer, render} = setup(props, setupContext); ctx._refer = refer; if (provideRefer) { if (!leftOptions.name) { console.error('designComponent: name is required when provideRefer is true!') } else { provide(`@@${leftOptions.name}`, refer); } } return render; } } as any), use: { ref: (refName: string) => { const ctx = (getCurrentInstance() as any).ctx; return { get value() { return ((ctx as any).$refs[refName].$._refer) as Refer | null; } } }, inject: (defalutValue?: any) => { return inject(`@@${leftOptions.name}`, defalutValue) as Refer; } } } }