UNPKG

tg-map-vue3

Version:

封装 百度地图, Google地图, Here地图(未完成) 的Vue3组件库

191 lines (190 loc) 8.48 kB
import { type Component, type ComponentOptions, type ComponentPublicInstance, type ComputedRef, type Prop, type PropType, type Ref, type RendererElement, type RendererNode, type Slots, type VNode, type WritableComputedOptions } from 'vue'; import type { AbstractConstructor, KeysMatching, StringEnumLike, StringEnumValue, Thing } from './mapped-types'; /** 组件选项中的hook名 */ export type VueHookName = ExcludeSubtype<KeysMatching<OmitStartsWith<RemoveIndex<ComponentOptions>, '_'>, { (): void; } | undefined>, 'serverPrefetch' | 'emits' | 'computed' | 'extends' | 'methods' | 'call' | undefined>; export type VueHookFunction = (this: ComponentPublicInstance) => void; /** * 模仿Vue的计算属性的写法 * @see ComputedOptions */ export type Property<T> = T | { (): T; } | { get(): T; set?(value: T): void; }; /** * ## Vue2 * 和typed()联合使用, 写成: `props: typed<Props<Options>>({...})`, 可以将`Options`作为属性的类型声明, * ### 注意 * 1. 对于`Options`中可选的属性, 漏了VSCode不会报错...要小心 * 2. `...`中理论上来说只要写Vue的纯js式的类型验证信息(Boolean/Number/String/Object/...)就行了, 并且还有ts的类型检查 * 3. 对于`Options`中可选的`boolean`属性, 若将类型验证信息写为`Boolean`时, 该属性的默认值并不是`undefined`而是`false`, 这和它的类型声明(`boolean | undefined`)不匹配, 推荐写成`optionalProp(Boolean)` * 4. 因为存在上述特殊情况, 推荐使用{@link requiredProp},{@link optionalProp}等快捷方法写类型验证信息, 方法的传入参数直接写Vue的纯js式的类型验证信息, 就行了 * * ## Vue3 * 需要用`props: {...} satisfies Props<Options>`替代`typed()`, 防止{@link NotNullProp}被Vue看成必选的属性 * */ export type Props<T> = { [K in keyof T]-?: T[K] extends {} ? NotNullProp<T[K]> : Prop<Exclude<T[K], undefined>>; }; /** 表示一个非空的Prop, `required`为true 或者 设置了`default`的{@link Prop}, 才是非空的Prop */ type NotNullProp<T = any, D = T> = { type: PropType<T>; } & ({ required: true; } | { default: D | (() => D); }); export declare function stringEnumProp<E extends StringEnumLike>(enumObject: E, defaultValue: E[keyof E]): { type: PropType<StringEnumValue<E>>; default: E[keyof E]; }; export declare function stringEnumProp<E extends StringEnumLike>(enumObject: E): { type: PropType<StringEnumValue<E>>; }; export declare function stringUnionPropFromValues<T extends string>(values: readonly T[], defaultValue: T): { type: PropType<T[][number]>; default: T; }; export declare function stringUnionPropFromValues<T extends string>(values: readonly T[]): { type: PropType<T[][number]>; }; export declare function requiredProp<T>(type: PropType<T>): { type: PropType<T>; required: true; }; export declare function optionalProp<T>(type: PropType<T>, defaultValue: T | (() => T)): { type: PropType<T>; default: T; }; export declare function optionalProp<T>(type: PropType<T>): { type: PropType<T>; }; /** * 保存在this上的属性 * @param defaultValues 属性的默认值 * * @deprecated Vue3中已经不支持`cache: false`的计算属性, 使用setup中返回普通的值替代 */ export declare function computedSaveOnThis<T>(defaultValues: { [K in keyof T]: T[K]; }): { [K in keyof T]: WritableComputedOptions<T[K]>; }; /** * 模仿Vue的计算属性的写法, 将方法转换成属性 * @deprecated 在Vue2时用来将provide的方法转换成属性, 方便使用, Vue3中不生效, 故废弃 */ export declare function createPropertyObject(obj: any): any; /** * 相比{@link createPropertyObject}增加类型信息 * @see createPropertyObject * @deprecated Vue3中没用 * */ export declare function createPropertyObjectTyped<T>(obj: { [K in keyof T]: Property<T[K]>; }): T; /** * 创建空节点 * * Vue2中使用`this._e()`创建空节点: https://github.com/vuejs/vue/blob/b6247fc9d7442c50d60ccf366a7cb183a4d02129/src/core/instance/render-helpers/index.js#L28 * * Vue3中等价的实现是{@link createCommentVNode}: https://github.com/vuejs/core/blob/650f5c26f464505d9e865bdb0eafb24350859528/packages/runtime-core/src/compat/instance.ts#L162 */ export declare function createEmptyVNode(): VNode; /** * @see https://github.com/vuejs/vue/blob/43b98fe25151b0b6bacd36f3ee27c5d61add5fdb/packages/weex-vue-framework/factory.js/#L2906 * */ export declare function callHook(vm: ComponentPublicInstance, hookName: VueHookName): void; /** * {@link import('./mapped-types.ts').safeAsComponent} * @deprecated Vue3已经不能遍历子组件的实例了, 所以这个方法目前没用 */ export declare function findByComponentType<T extends Component & AbstractConstructor>(arr: ComponentPublicInstance[], component: T): InstanceType<T> | undefined; /** * 通过构造slots内容的方式, 提取出slots中对应{@link component}的VNode, {@link VNode.props}就是当前给组件设置的属性值 * * 注意, 该方法并无法获取到{@link component}的实例 * * @see https://stackoverflow.com/questions/64154002/vue-3-how-to-get-information-about-children */ export declare function extractVNodeFromSlotsByComponent<Props>(slots: Slots, component: ComponentOptions<Props>): VNode<RendererNode, RendererElement, Props> | undefined; /** * Vue3中 class/style/未声明的事件/未声明的属性 都会集合到`this.$attrs`中 * 默认情况下(`inheritAttrs`为true), 将被透传给组件的根节点 * * 而Vue2, `this.$attrs`值包含 未声明的属性, 所有事件放到了`this.$listeners`中 * * 这里模仿Vue2的行为, 从{@link attrs}中拆分出未声明的事件, 方便将他们透传给地图的对象 * 同时若传入{@link props}, 也会从它里面拆分出 声明的事件类型的属性 * * ## 如何给事件添加类型信息 * * - 声明在`emits`中的事件, 会给emit方法添加类型信息, 但没办法在运行时判断是否有被设置 * - 声明在`props`中的事件, 不会.................. , 但可以通过读取`this.$props`判断是否被设置 * * 所有我们最终选择用{@link EventProps}在`props`中声明事件, 同时用{@link EventEmits}在`emits`上声明事件的类型, * 达到既有类型信息, 又能判断是否存在的效果, 写法如下: * ``` * { * props: {...} satisfies EventProps<TgMapEmits>, * emits: undefined as any as EventEmits<TgMapEmits>, * } * ``` * * ## 参考 * - https://cn.vuejs.org/guide/components/attrs.html#disabling-attribute-inheritance * - https://v3-migration.vuejs.org/zh/breaking-changes/listeners-removed.html * - https://eslint.vuejs.org/rules/require-explicit-emits.html#options */ export declare function splitAttrs(attrs: Record<string, unknown>, props?: Record<string, unknown>): { /** class/style/未声明的属性 等 */ binds: Record<string, unknown>; /** 未声明的事件 */ listeners: Record<string, unknown>; /** 声明在`props`中的事件 */ listenerProps: Record<string, unknown>; }; /** 响应式的{@link splitAttrs} */ export declare function useSplittedAttrs(attrs: Record<string, unknown>, props?: Record<string, unknown>): ComputedRef<{ /** class/style/未声明的属性 等 */ binds: Record<string, unknown>; /** 未声明的事件 */ listeners: Record<string, unknown>; /** 声明在`props`中的事件 */ listenerProps: Record<string, unknown>; }>; export type EventCallback<E = any> = (event: E) => void; /** * 事件类型的属性 * @see splitAttrs * */ export type EventProps<Emits> = Emits extends string ? { [K in Emits as `on${Capitalize<K>}`]: Prop<Function>; } : { [K in keyof Emits as K extends string ? `on${Capitalize<K>}` : never]: Prop<EventCallback<Emits[K]>>; }; /** * 用来声明事件的类型信息 * @see splitAttrs * */ export type EventEmits<T> = { [K in keyof T]: (event: T[K]) => boolean; }; /** 给事件类型的属性标注类型 */ export declare function eventProp<E = any>(): Prop<EventCallback<E>>; export declare const useEventLogMethods: () => { eventLog: (event: Thing | null | undefined) => void; eventLogLess: (this: any, event: Thing | null | undefined) => void; }; /** * 值可能是Ref的对象 * 可以用来给{@link reactive}的参数做类型约束 * */ export type MaybeWrapRefs<T> = { [P in keyof T]: Ref<T[P]> | T[P] | ComputedRef<T[P]>; }; export {};