33 <!-- #ifdef MP-DINGTALK -->
44 <view class =" wd-index-bar" :id =" indexBarId" >
55 <!-- #endif -->
6- <scroll-view :scrollTop =" scrollTop" :scroll-y =" true" class =" wd-index-bar__content" @scroll =" hanleScroll" >
6+ <scroll-view :scrollTop =" scrollState. scrollTop" :scroll-y =" true" class =" wd-index-bar__content" @scroll =" hanleScroll" >
77 <slot ></slot >
88 </scroll-view >
99 <view
1010 class =" wd-index-bar__sidebar"
11+ @touchstart.stop.prevent =" handleTouchStart"
1112 @touchmove.stop.prevent =" handleTouchMove"
1213 @touchend.stop.prevent =" handleTouchEnd"
1314 @touchcancel.stop.prevent =" handleTouchEnd"
3031<script setup lang="ts">
3132import type { AnchorItem , AnchorIndex } from ' ./type'
3233import { indexBarInjectionKey , indexBarProps } from ' ./type'
33- import { ref , getCurrentInstance , onMounted , reactive } from ' vue'
34- import { getRect , isDef , uuid } from ' ../common/util'
34+ import { ref , getCurrentInstance , onMounted , reactive , nextTick } from ' vue'
35+ import { getRect , isDef , uuid , requestAnimationFrame } from ' ../common/util'
3536import { useChildren } from ' ../composables/useChildren'
3637
3738const props = defineProps (indexBarProps )
@@ -49,7 +50,12 @@ const { linkChildren } = useChildren(indexBarInjectionKey)
4950
5051linkChildren ({ props , anchorState: state })
5152
52- const scrollTop = ref (0 )
53+ const scrollState = reactive ({
54+ scrollTop: 0 , // 即将滚动到的位置
55+ prevScrollTop: 0 , // 上次记录的位置
56+ // 滚动距离
57+ touching: false
58+ })
5359
5460// 组件距离页面顶部的高度
5561let offsetTop = 0
@@ -63,7 +69,6 @@ let sidebarInfo = {
6369function init() {
6470 setTimeout (() => {
6571 state .activeIndex = state .anchorList [0 ]?.index
66-
6772 Promise .all ([
6873 getRect (` #${indexBarId .value } ` , false , proxy ),
6974 getRect (' .wd-index-bar__sidebar' , false , proxy ),
@@ -81,6 +86,9 @@ onMounted(() => {
8186})
8287
8388function hanleScroll(scrollEvent : any ) {
89+ if (scrollState .touching ) {
90+ return
91+ }
8492 const { detail } = scrollEvent
8593 const scrolltop = Math .floor (detail .scrollTop )
8694 const anchor = state .anchorList .find ((item , index ) => {
@@ -91,6 +99,7 @@ function hanleScroll(scrollEvent: any) {
9199 if (state .activeIndex !== anchor .index ) {
92100 state .activeIndex = anchor .index
93101 }
102+ scrollState .prevScrollTop = scrolltop
94103}
95104
96105function getAnchorByPageY(pageY : number ) {
@@ -101,18 +110,37 @@ function getAnchorByPageY(pageY: number) {
101110 return state .anchorList [idx ]
102111}
103112
113+ function handleTouchStart() {
114+ scrollState .touching = true
115+ }
116+
104117function handleTouchMove(e : TouchEvent ) {
105118 const clientY = e .touches [0 ].pageY
106119 if (state .activeIndex === getAnchorByPageY (clientY ).index ) {
107120 return
108121 }
109122 state .activeIndex = getAnchorByPageY (clientY ).index
110- scrollTop . value = getAnchorByPageY (clientY ).top - offsetTop
123+ setScrollTop ( getAnchorByPageY (clientY ).top - offsetTop )
111124}
112125
113126function handleTouchEnd(e : TouchEvent ) {
114127 const clientY = e .changedTouches [0 ].pageY
115- scrollTop .value = getAnchorByPageY (clientY ).top - offsetTop
128+ state .activeIndex = getAnchorByPageY (clientY ).index
129+ setScrollTop (getAnchorByPageY (clientY ).top - offsetTop )
130+ requestAnimationFrame (() => {
131+ scrollState .touching = false
132+ })
133+ }
134+
135+ function setScrollTop(top : number ) {
136+ if (scrollState .scrollTop === top ) {
137+ scrollState .scrollTop = scrollState .prevScrollTop
138+ nextTick (() => {
139+ scrollState .scrollTop = top
140+ })
141+ } else {
142+ scrollState .scrollTop = top
143+ }
116144}
117145 </script >
118146
0 commit comments