From 407c7b052192f9376553b8053dc612abddc9a27d Mon Sep 17 00:00:00 2001 From: icssoa <615206459@qq.com> Date: Mon, 11 Aug 2025 23:48:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=A1=B5=E9=9D=A2=E6=BB=9A?= =?UTF-8?q?=E5=8A=A8=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cool/index.ts | 15 ++++--- cool/scroller/index.ts | 23 +++++++++++ pages/demo/data/list-view.uvue | 12 +++++- .../components/cl-back-top/cl-back-top.uvue | 33 +++++++++------ .../components/cl-list-view/cl-list-view.uvue | 37 +++++++++++------ .../cool-ui/components/cl-page/cl-page.uvue | 13 +++--- .../components/cl-sticky/cl-sticky.uvue | 20 +++++----- uni_modules/cool-ui/hooks/page.ts | 40 ++++++------------- 8 files changed, 119 insertions(+), 74 deletions(-) create mode 100644 cool/scroller/index.ts diff --git a/cool/index.ts b/cool/index.ts index 5366631..0a3bb01 100644 --- a/cool/index.ts +++ b/cool/index.ts @@ -1,8 +1,12 @@ +import { scroller } from "./scroller"; import { initTheme, setH5 } from "./theme"; import { initLocale } from "@/locale"; export function cool(app: VueApp) { app.mixin({ + onPageScroll(e) { + scroller.emit(e.scrollTop); + }, onShow() { // #ifdef H5 setTimeout(() => { @@ -18,11 +22,12 @@ export function cool(app: VueApp) { console.log(app); } -export * from "./utils"; -export * from "./theme"; -export * from "./router"; -export * from "./service"; -export * from "./hooks"; export * from "./ctx"; +export * from "./hooks"; +export * from "./router"; +export * from "./scroller"; +export * from "./service"; export * from "./store"; +export * from "./theme"; export * from "./upload"; +export * from "./utils"; diff --git a/cool/scroller/index.ts b/cool/scroller/index.ts new file mode 100644 index 0000000..39f7732 --- /dev/null +++ b/cool/scroller/index.ts @@ -0,0 +1,23 @@ +import { router } from "../router"; + +class Scroller { + list: Map void)[]> = new Map(); + + // 触发滚动 + emit(top: number) { + const cbs = this.list.get(router.path()) ?? []; + cbs.forEach((cb) => { + cb(top); + }); + } + + // 监听页面滚动 + on(callback: (top: number) => void) { + const path = router.path(); + const cbs = this.list.get(path) ?? []; + cbs.push(callback); + this.list.set(path, cbs); + } +} + +export const scroller = new Scroller(); diff --git a/pages/demo/data/list-view.uvue b/pages/demo/data/list-view.uvue index 186c649..339ba59 100644 --- a/pages/demo/data/list-view.uvue +++ b/pages/demo/data/list-view.uvue @@ -17,6 +17,9 @@ :pt="{ indexBar: { className: '!fixed' + }, + itemHover: { + className: 'bg-gray-200' } }" > @@ -29,12 +32,16 @@ diff --git a/uni_modules/cool-ui/components/cl-back-top/cl-back-top.uvue b/uni_modules/cool-ui/components/cl-back-top/cl-back-top.uvue index 4fa13f6..6245289 100644 --- a/uni_modules/cool-ui/components/cl-back-top/cl-back-top.uvue +++ b/uni_modules/cool-ui/components/cl-back-top/cl-back-top.uvue @@ -12,7 +12,7 @@ diff --git a/uni_modules/cool-ui/components/cl-list-view/cl-list-view.uvue b/uni_modules/cool-ui/components/cl-list-view/cl-list-view.uvue index 80a43f8..8c67ece 100644 --- a/uni_modules/cool-ui/components/cl-list-view/cl-list-view.uvue +++ b/uni_modules/cool-ui/components/cl-list-view/cl-list-view.uvue @@ -1,16 +1,6 @@ @@ -295,6 +307,7 @@ const { proxy } = getCurrentInstance()!; type PassThrough = { className?: string; item?: PassThroughProps; + itemHover?: PassThroughProps; list?: PassThroughProps; indexBar?: PassThroughProps; scroller?: PassThroughProps; diff --git a/uni_modules/cool-ui/components/cl-page/cl-page.uvue b/uni_modules/cool-ui/components/cl-page/cl-page.uvue index 927caae..b91733f 100644 --- a/uni_modules/cool-ui/components/cl-page/cl-page.uvue +++ b/uni_modules/cool-ui/components/cl-page/cl-page.uvue @@ -6,7 +6,7 @@ :scroll-with-animation="true" @scroll="onScroll" > - + @@ -14,7 +14,7 @@ - + @@ -27,7 +27,7 @@ import Theme from "./theme.uvue"; import Ui from "./ui.uvue"; import { locale, t } from "@/locale"; import { config } from "@/config"; -import { router } from "@/cool"; +import { router, scroller } from "@/cool"; defineOptions({ name: "cl-page" @@ -49,12 +49,13 @@ const scrollViewTop = ref(0); // view 滚动事件 function onScroll(e: UniScrollEvent) { - scrollTop.value = e.detail.scrollTop; + // 触发滚动事件 + scroller.emit(e.detail.scrollTop); } // 页面滚动事件 -onPageScroll((e) => { - scrollTop.value = e.scrollTop; +scroller.on((top) => { + scrollTop.value = top; }); // 滚动到指定位置 diff --git a/uni_modules/cool-ui/components/cl-sticky/cl-sticky.uvue b/uni_modules/cool-ui/components/cl-sticky/cl-sticky.uvue index 1a3c5aa..3cbbc3c 100644 --- a/uni_modules/cool-ui/components/cl-sticky/cl-sticky.uvue +++ b/uni_modules/cool-ui/components/cl-sticky/cl-sticky.uvue @@ -57,9 +57,9 @@ const props = defineProps({ const { proxy } = getCurrentInstance()!; // cl-page 上下文 -const page = usePage(); +const { onScroll } = usePage(); -// 定义Rect类型,表示元素的位置信息 +// 表示元素的位置信息 type Rect = { height: number; // 高度 width: number; // 宽度 @@ -67,7 +67,7 @@ type Rect = { top: number; // 距离页面顶部的距离 }; -// rect为响应式对象,存储当前sticky元素的位置信息 +// 存储当前sticky元素的位置信息 const rect = reactive({ height: 0, width: 0, @@ -75,7 +75,7 @@ const rect = reactive({ top: 0 }); -// scrollTop为当前页面滚动的距离 +// 当前页面滚动的距离 const scrollTop = ref(0); // 计算属性,判断当前是否处于吸顶状态 @@ -128,14 +128,16 @@ function getRect() { }); } -// 监听页面滚动事件 -page.onPageScroll((top) => { - scrollTop.value = top; -}); - onMounted(() => { + // 获取元素位置信息 getRect(); + // 监听页面滚动事件 + onScroll((top) => { + scrollTop.value = top; + }); + + // 监听参数变化 watch( computed(() => props.scrollTop), (top: number) => { diff --git a/uni_modules/cool-ui/hooks/page.ts b/uni_modules/cool-ui/hooks/page.ts index 10fafc1..e01bcb3 100644 --- a/uni_modules/cool-ui/hooks/page.ts +++ b/uni_modules/cool-ui/hooks/page.ts @@ -1,66 +1,50 @@ -import { router, useParent } from "@/cool"; -import { computed, watch } from "vue"; - -type PageScrollCallback = (top: number) => void; +import { router, scroller, useParent } from "@/cool"; class Page { - listeners: PageScrollCallback[] = []; pageRef: ClPageComponentPublicInstance | null = null; constructor() { this.pageRef = useParent("cl-page"); - - if (this.pageRef != null) { - // TODO: 小程序异常 - watch( - computed(() => this.pageRef!.scrollTop), - (top: number) => { - this.listeners.forEach((listener) => { - listener(top); - }); - } - ); - } } /** * 获取页面路径 * @returns 页面路径 */ - path() { + path = () => { return router.path(); - } + }; /** * 获取滚动位置 * @returns 滚动位置 */ - getScrollTop(): number { + getScrollTop = (): number => { return this.pageRef!.scrollTop as number; - } + }; /** * 滚动到指定位置 * @param top 滚动位置 */ - scrollTo(top: number) { + scrollTo = (top: number) => { this.pageRef!.scrollTo(top); - } + }; /** * 回到顶部 */ - scrollToTop() { + scrollToTop = () => { this.pageRef!.scrollToTop(); - } + }; /** * 监听页面滚动 * @param callback 回调函数 */ - onPageScroll(callback: PageScrollCallback) { - this.listeners.push(callback); - } + onScroll = (callback: (top: number) => void) => { + scroller.on(callback); + }; } export function usePage(): Page {