tg-map-vue3
Version:
封装 百度地图, Google地图, Here地图(未完成) 的Vue3组件库
191 lines (190 loc) • 8.48 kB
TypeScript
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 {};