版本发布
This commit is contained in:
28
cool/hooks/cache.ts
Normal file
28
cool/hooks/cache.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { reactive, watch } from "vue";
|
||||
import { isDark } from "../theme";
|
||||
|
||||
type CacheData = {
|
||||
key: number;
|
||||
};
|
||||
|
||||
type UseCache = {
|
||||
cache: CacheData;
|
||||
};
|
||||
|
||||
export const useCache = (source: () => any[]): UseCache => {
|
||||
const cache = reactive<CacheData>({
|
||||
key: 0
|
||||
});
|
||||
|
||||
watch(source, () => {
|
||||
cache.key++;
|
||||
});
|
||||
|
||||
watch(isDark, () => {
|
||||
cache.key++;
|
||||
});
|
||||
|
||||
return {
|
||||
cache
|
||||
};
|
||||
};
|
||||
5
cool/hooks/index.ts
Normal file
5
cool/hooks/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from "./refs";
|
||||
export * from "./page";
|
||||
export * from "./long-press";
|
||||
export * from "./cache";
|
||||
export * from "./parent";
|
||||
100
cool/hooks/long-press.ts
Normal file
100
cool/hooks/long-press.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { vibrate } from "@/uni_modules/cool-vibrate";
|
||||
import { onUnmounted } from "vue";
|
||||
|
||||
// 长按触发延迟时间,单位毫秒
|
||||
const DELAY = 500;
|
||||
// 长按重复执行间隔时间,单位毫秒
|
||||
const REPEAT = 100;
|
||||
|
||||
/**
|
||||
* 长按操作钩子函数返回类型
|
||||
*/
|
||||
type UseLongPress = {
|
||||
// 开始长按
|
||||
start: (cb: () => void) => void;
|
||||
// 停止长按
|
||||
stop: () => void;
|
||||
// 清除定时器
|
||||
clear: () => void;
|
||||
// 是否正在长按中
|
||||
isPressing: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* 长按操作钩子函数
|
||||
* 支持长按持续触发,可用于数字输入框等需要连续操作的场景
|
||||
*/
|
||||
export const useLongPress = (): UseLongPress => {
|
||||
// 长按延迟定时器
|
||||
let pressTimer: number = 0;
|
||||
// 重复执行定时器
|
||||
let repeatTimer: number = 0;
|
||||
// 是否正在长按中
|
||||
let isPressing = false;
|
||||
|
||||
/**
|
||||
* 清除所有定时器
|
||||
* 重置长按状态
|
||||
*/
|
||||
const clear = () => {
|
||||
// 清除长按延迟定时器
|
||||
if (pressTimer != 0) {
|
||||
clearTimeout(pressTimer);
|
||||
pressTimer = 0;
|
||||
}
|
||||
// 清除重复执行定时器
|
||||
if (repeatTimer != 0) {
|
||||
clearInterval(repeatTimer);
|
||||
repeatTimer = 0;
|
||||
}
|
||||
// 重置长按状态
|
||||
isPressing = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* 开始长按操作
|
||||
* @param cb 长按时重复执行的回调函数
|
||||
*/
|
||||
const start = (cb: () => void) => {
|
||||
// 清除已有定时器
|
||||
clear();
|
||||
|
||||
// 立即执行一次回调
|
||||
cb();
|
||||
|
||||
// 延迟500ms后开始长按
|
||||
// @ts-ignore
|
||||
pressTimer = setTimeout(() => {
|
||||
// 震动
|
||||
vibrate(1);
|
||||
|
||||
// 设置长按状态
|
||||
isPressing = true;
|
||||
// 每100ms重复执行回调
|
||||
// @ts-ignore
|
||||
repeatTimer = setInterval(() => {
|
||||
cb();
|
||||
}, REPEAT);
|
||||
}, DELAY);
|
||||
};
|
||||
|
||||
/**
|
||||
* 停止长按操作
|
||||
* 清除定时器并重置状态
|
||||
*/
|
||||
const stop = () => {
|
||||
clear();
|
||||
};
|
||||
|
||||
// 组件卸载时清理定时器
|
||||
onUnmounted(() => {
|
||||
clear();
|
||||
});
|
||||
|
||||
return {
|
||||
start,
|
||||
stop,
|
||||
clear,
|
||||
isPressing
|
||||
};
|
||||
};
|
||||
94
cool/hooks/page.ts
Normal file
94
cool/hooks/page.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { config } from "@/config";
|
||||
import { router } from "../router";
|
||||
import { getPx, isH5, isHarmony } from "../utils";
|
||||
import { ctx } from "../ctx";
|
||||
|
||||
class Page {
|
||||
scrolls: Map<string, ((top: number) => void)[]> = new Map();
|
||||
|
||||
path() {
|
||||
return router.path();
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发滚动事件
|
||||
* @param top 滚动距离
|
||||
*/
|
||||
triggerScroll(top: number) {
|
||||
const callbacks = this.scrolls.get(this.path()) ?? [];
|
||||
callbacks.forEach((cb) => {
|
||||
cb(top);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册滚动事件回调
|
||||
* @param callback 回调函数
|
||||
*/
|
||||
onPageScroll(callback: (top: number) => void) {
|
||||
const callbacks = this.scrolls.get(this.path()) ?? [];
|
||||
callbacks.push(callback);
|
||||
this.scrolls.set(this.path(), callbacks);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否需要计算 tabBar 高度
|
||||
* @returns boolean
|
||||
*/
|
||||
hasCustomTabBar() {
|
||||
if (router.isTabPage()) {
|
||||
if (isHarmony()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return config.isCustomTabBar || isH5();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 tabBar 高度
|
||||
* @returns tabBar 高度
|
||||
*/
|
||||
getTabBarHeight() {
|
||||
let h = ctx.tabBar.height == null ? 50 : getPx(ctx.tabBar.height!);
|
||||
|
||||
if (this.hasCustomTabBar()) {
|
||||
h += this.getSafeAreaHeight("bottom");
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取安全区域高度
|
||||
* @param type 类型
|
||||
* @returns 安全区域高度
|
||||
*/
|
||||
getSafeAreaHeight(type: "top" | "bottom") {
|
||||
const { safeAreaInsets } = uni.getWindowInfo();
|
||||
|
||||
let h: number;
|
||||
|
||||
if (type == "top") {
|
||||
h = safeAreaInsets.top;
|
||||
} else {
|
||||
h = safeAreaInsets.bottom;
|
||||
|
||||
// #ifdef APP-ANDROID
|
||||
if (h == 0) {
|
||||
h = 16;
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
export const page = new Page();
|
||||
|
||||
export function usePage(): Page {
|
||||
return page;
|
||||
}
|
||||
22
cool/hooks/parent.ts
Normal file
22
cool/hooks/parent.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { getCurrentInstance } from "vue";
|
||||
|
||||
/**
|
||||
* 获取父组件实例
|
||||
*
|
||||
* 用于在子组件中获取父组件实例,以便访问父组件的属性和方法
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // 在子组件中使用
|
||||
* const parent = useParent<ParentType>();
|
||||
* // 访问父组件属性
|
||||
* console.log(parent.someProperty);
|
||||
* ```
|
||||
*
|
||||
* @template T 父组件实例的类型
|
||||
* @returns {T} 返回父组件实例
|
||||
*/
|
||||
export function useParent<T>(): T {
|
||||
const { proxy } = getCurrentInstance()!;
|
||||
return proxy?.$parent as T;
|
||||
}
|
||||
120
cool/hooks/refs.ts
Normal file
120
cool/hooks/refs.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
import { reactive } from "vue";
|
||||
import { isNull } from "../utils";
|
||||
|
||||
// #ifdef APP
|
||||
type Instance = ComponentPublicInstance | null;
|
||||
// #endif
|
||||
|
||||
// #ifndef APP
|
||||
type Instance = any;
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* Refs 类用于管理组件引用,便于在组合式 API 中获取、操作子组件实例。
|
||||
*/
|
||||
class Refs {
|
||||
// 存储所有 ref 的响应式对象,key 为 ref 名称,value 为组件实例
|
||||
data = reactive({} as UTSJSONObject);
|
||||
|
||||
/**
|
||||
* 生成 ref 绑定函数,用于在模板中设置 ref。
|
||||
* @param name ref 名称
|
||||
* @returns 绑定函数 (el: Instance) => void
|
||||
*/
|
||||
set(name: string) {
|
||||
return (el: Instance) => {
|
||||
this.data[name] = el;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定名称的组件实例
|
||||
* @param name ref 名称
|
||||
* @returns 组件实例或 null
|
||||
*/
|
||||
get(name: string): Instance {
|
||||
const d = this.data[name] as ComponentPublicInstance;
|
||||
|
||||
if (isNull(d)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取组件实例暴露的属性或方法(兼容不同平台)
|
||||
* @param name ref 名称
|
||||
* @param key 暴露的属性名
|
||||
* @returns 属性值或 null
|
||||
*/
|
||||
getExposed<T>(name: string, key: string): T | null {
|
||||
// #ifdef APP-ANDROID
|
||||
const d = this.get(name);
|
||||
|
||||
if (isNull(d)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 安卓平台下,$exposed 为 Map<string, any>
|
||||
const ex = d!.$exposed as Map<string, any>;
|
||||
|
||||
if (isNull(ex)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ex[key] as T | null;
|
||||
// #endif
|
||||
|
||||
// #ifndef APP-ANDROID
|
||||
// 其他平台直接通过属性访问
|
||||
return this.get(name)?.[key] as T;
|
||||
// #endif
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用组件实例暴露的方法,并返回结果
|
||||
* @param name ref 名称
|
||||
* @param method 方法名
|
||||
* @param data 传递的数据
|
||||
* @returns 方法返回值
|
||||
*/
|
||||
call<T>(name: string, method: string, data: UTSJSONObject | null = null): T {
|
||||
return this.get(name)!.$callMethod(method, data) as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用组件实例暴露的方法,无返回值
|
||||
* @param name ref 名称
|
||||
* @param method 方法名
|
||||
* @param data 传递的数据
|
||||
*/
|
||||
callMethod(name: string, method: string, data: UTSJSONObject | null = null): void {
|
||||
this.get(name)!.$callMethod(method, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用组件的 open 方法,常用于弹窗、抽屉等组件
|
||||
* @param name ref 名称
|
||||
* @param data 传递的数据
|
||||
*/
|
||||
open(name: string, data: UTSJSONObject | null = null) {
|
||||
this.callMethod(name, "open", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用组件的 close 方法,常用于弹窗、抽屉等组件
|
||||
* @param name ref 名称
|
||||
*/
|
||||
close(name: string) {
|
||||
return this.callMethod(name, "close");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* useRefs 组合式函数,返回 Refs 实例
|
||||
* @returns Refs 实例
|
||||
*/
|
||||
export function useRefs(): Refs {
|
||||
return new Refs();
|
||||
}
|
||||
Reference in New Issue
Block a user