Skip to content

Commit 56a2ed5

Browse files
committed
fix: taro h5 端滚动错乱修复
1 parent d8e267a commit 56a2ed5

File tree

8 files changed

+105
-82
lines changed

8 files changed

+105
-82
lines changed

src/packages/elevator/demos/taro/demo5.tsx

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,20 @@ const Demo5 = () => {
2727
title: 'G',
2828
list: [
2929
{
30-
name: '广西',
31-
id: 3,
30+
name: '甘肃',
31+
id: 31,
3232
},
3333
{
3434
name: '广东',
35-
id: 4,
35+
id: 32,
36+
},
37+
{
38+
name: '广东',
39+
id: 33,
40+
},
41+
{
42+
name: '贵州',
43+
id: 34,
3644
},
3745
],
3846
},
@@ -41,15 +49,44 @@ const Demo5 = () => {
4149
list: [
4250
{
4351
name: '湖南',
44-
id: 5,
52+
id: 41,
53+
},
54+
{
55+
name: '湖北',
56+
id: 42,
4557
},
4658
{
4759
name: '湖北',
48-
id: 6,
60+
id: 43,
61+
},
62+
{
63+
name: '湖南',
64+
id: 44,
65+
},
66+
{
67+
name: '海南',
68+
id: 45,
69+
},
70+
],
71+
},
72+
{
73+
title: 'S',
74+
list: [
75+
{
76+
name: '山东',
77+
id: 51,
78+
},
79+
{
80+
name: '山西',
81+
id: 52,
82+
},
83+
{
84+
name: '上海',
85+
id: 53,
4986
},
5087
{
51-
name: '河南',
52-
id: 7,
88+
name: '陕西',
89+
id: 54,
5390
},
5491
],
5592
},

src/packages/elevator/doc.en-US.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ import { Elevator } from '@nutui/nutui-react'
6161
| list | Index list | `Array(item needs to contain id and name attributes, and name supports passing in html structure)` | `[{id: 0, name: ''}]` |
6262
| sticky | Whether the index is ceiling | `boolean` | `false` |
6363
| showKeys | Show right navigation | `boolean` | `true` |
64-
| spaceHeight | Up and down spacing of right anchor point | `number` | `23` |
65-
| titleHeight | Height of left index | `number` | `35` |
64+
| spaceHeight | Up and down spacing of right anchor point | `number` | `18` |
6665
| onItemClick | Click content | `onItemClick:(key: string, item: { id: number, name: string })=>void` | `false` |
6766
| onIndexClick | Click index | `onIndexClick:(key: string)=>void` | `false` |
6867

src/packages/elevator/doc.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ import { Elevator } from '@nutui/nutui-react'
6161
| list | 索引列表 | `Array(item 需包含 id、name 属性, name 支持传入 html 结构)` | `[{id: 0, name: ''}]` |
6262
| sticky | 索引是否吸顶 | `boolean` | `false` |
6363
| showKeys | 展示右侧导航 | `boolean` | `true` |
64-
| spaceHeight | 右侧锚点的上下间距 | `number` | `23` |
65-
| titleHeight | 左侧索引的高度 | `number` | `35` |
64+
| spaceHeight | 右侧锚点的上下间距 | `number` | `18` |
6665
| onItemClick | 点击内容 | `onItemClick:(key: string, item: { id: number, name: string })=>void` | `false` |
6766
| onIndexClick | 点击索引 | `onIndexClick:(key: string)=>void` | `false` |
6867

src/packages/elevator/doc.taro.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ import { Elevator } from '@nutui/nutui-react-taro'
6161
| list | 索引列表 | `Array(item 需包含 id、name 属性, name 支持传入 html 结构)` | `[{id: 0, name: ''}]` |
6262
| sticky | 索引是否吸顶 | `boolean` | `false` |
6363
| showKeys | 展示右侧导航 | `boolean` | `true` |
64-
| spaceHeight | 右侧锚点的上下间距 | `number` | `23` |
65-
| titleHeight | 左侧索引的高度 | `number` | `35` |
64+
| spaceHeight | 右侧锚点的上下间距 | `number` | `18` |
6665
| onItemClick | 点击内容 | `onItemClick:(key: string, item: { id: number, name: string })=>void` | `false` |
6766
| onIndexClick | 点击索引 | `onIndexClick:(key: string)=>void` | `false` |
6867

src/packages/elevator/doc.zh-TW.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ import { Elevator } from '@nutui/nutui-react'
6161
| list | 索引列表 | `Array(item 需包含 id、name 屬性, name 支持傳入 html 結構)` | `[{id: 0, name: ''}]` |
6262
| sticky | 索引是否吸頂 | `boolean` | `false` |
6363
| showKeys | 展示右側導航 | `boolean` | `true` |
64-
| spaceHeight | 右側錨點的上下間距 | `number` | `23` |
65-
| titleHeight | 左側索引的高度 | `number` | `35` |
64+
| spaceHeight | 右側錨點的上下間距 | `number` | `18` |
6665
| onItemClick | 點擊內容 | `onItemClick:(key: string, item: { id: number, name: string })=>void` | `false` |
6766
| onIndexClick | 點擊索引 | `onIndexClick:(key: string)=>void` | `false` |
6867

src/packages/elevator/elevator.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@
8888
position: absolute;
8989
right: $elevator-bars-right;
9090
top: $elevator-bars-top;
91-
font-size: $elevator-bars-font-size;
9291
transform: $elevator-bars-transform;
9392
z-index: $elevator-bars-z-index;
9493

@@ -104,6 +103,7 @@
104103
border-radius: 50%;
105104
margin: 1px 0;
106105
color: $elevator-bars-color;
106+
font-size: $elevator-bars-font-size;
107107
cursor: pointer;
108108
&-active {
109109
font-weight: $font-weight-bold;

src/packages/elevator/elevator.taro.tsx

Lines changed: 55 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import classNames from 'classnames'
1212
import { BasicComponent, ComponentDefaults } from '@/utils/typings'
1313
import { harmony } from '@/utils/taro/platform'
1414
import { useUuid } from '@/hooks/use-uuid'
15+
import raf from '@/utils/raf'
1516

1617
export const elevatorContext = createContext({} as ElevatorData)
1718

@@ -22,7 +23,6 @@ export interface ElevatorProps extends BasicComponent {
2223
list: any[]
2324
sticky: boolean
2425
spaceHeight: number
25-
titleHeight: number
2626
showKeys: boolean
2727
onItemClick: (key: string, item: ElevatorData) => void
2828
onIndexClick: (key: string) => void
@@ -34,10 +34,8 @@ const defaultProps = {
3434
floorKey: 'title',
3535
list: [] as any[],
3636
sticky: false,
37-
spaceHeight: 23,
38-
titleHeight: 35,
37+
spaceHeight: 18,
3938
showKeys: true,
40-
className: 'weapp-elevator',
4139
} as ElevatorProps
4240
interface ElevatorData {
4341
name: string
@@ -54,7 +52,6 @@ export const Elevator: FunctionComponent<
5452
list,
5553
sticky,
5654
spaceHeight,
57-
titleHeight,
5855
showKeys,
5956
className,
6057
style,
@@ -68,11 +65,10 @@ export const Elevator: FunctionComponent<
6865
}
6966
const uuid = useUuid()
7067
const classPrefix = 'nut-elevator'
71-
const listview = useRef<HTMLDivElement>(null)
68+
7269
const initData = {
7370
anchorIndex: 0,
7471
listHeight: [] as number[],
75-
listGroup: [] as any[],
7672
scrollY: 0,
7773
}
7874
const touchState = useRef({
@@ -102,29 +98,35 @@ export const Elevator: FunctionComponent<
10298
}
10399

104100
const calculateHeight = () => {
105-
let height = 0
101+
state.current.listHeight = [0]
106102

107-
state.current.listHeight.push(height)
108-
for (let i = 0; i < state.current.listGroup.length; i++) {
109-
const query = createSelectorQuery()
110-
query
111-
.selectAll(`.${classPrefix}-${uuid} .nut-elevator-item-${i}`)
112-
.boundingClientRect()
113-
// eslint-disable-next-line no-loop-func
114-
query.exec((res: any) => {
115-
if (res[0][0]) height += res[0][0].height
116-
state.current.listHeight.push(height)
103+
const query = createSelectorQuery()
104+
query
105+
.selectAll(`#${classPrefix}-${uuid} .${classPrefix}-list-item`)
106+
.boundingClientRect()
107+
.exec((rect = []) => {
108+
if (rect[0] && rect[0].length) {
109+
// rect[0] = rect[0].reverse()
110+
state.current.listHeight = rect[0].reduce(
111+
(acc: any[], item: { height: any }, index: number) => {
112+
// 当前项的高度等于前面所有项的高度之和
113+
const height = acc[index] + item.height
114+
acc.push(height)
115+
return acc
116+
},
117+
[0]
118+
)
119+
}
117120
})
118-
}
119121
}
120122

121-
const scrollTo = (index: number) => {
123+
const scrollTo = async (index: number) => {
122124
if (!index && index !== 0) {
123125
return
124126
}
125127

126128
if (!state.current.listHeight.length) {
127-
calculateHeight()
129+
await calculateHeight()
128130
}
129131
let cacheIndex = index
130132
if (index < 0) {
@@ -138,7 +140,7 @@ export const Elevator: FunctionComponent<
138140
setCodeIndex(cacheIndex)
139141
const scrollTop = state.current.listHeight[cacheIndex]
140142
setScrollTop(scrollTop)
141-
if (sticky && scrollY !== scrollTop) {
143+
if (mode === 'vertical' && sticky) {
142144
setScrollY(Math.floor(scrollTop) > 0 ? 1 : 0)
143145
}
144146
}
@@ -178,38 +180,31 @@ export const Elevator: FunctionComponent<
178180
onIndexClick && onIndexClick(key)
179181
}
180182

181-
const setListGroup = () => {
182-
if (listview.current) {
183-
createSelectorQuery()
184-
.selectAll(`.${classPrefix}-${uuid} .nut-elevator-list-item`)
185-
.node((el) => {
186-
state.current.listGroup = [...Object.keys(el)]
187-
calculateHeight()
188-
})
189-
.exec()
190-
}
191-
}
192-
193183
const listViewScroll = (e: any) => {
194-
const { listHeight } = state.current
195-
if (!listHeight.length) {
196-
calculateHeight()
197-
}
198-
const target = e.target as Element
199-
const { scrollTop } = target
200-
state.current.scrollY = Math.floor(scrollTop)
201-
Taro.getEnv() === 'WEB' && setScrollTop(scrollTop)
202-
if (sticky && scrollTop !== scrollY) {
203-
setScrollY(Math.floor(scrollTop) > 0 ? 1 : 0)
204-
}
205-
if (scrolling.current) return
206-
for (let i = 0; i < listHeight.length - 1; i++) {
207-
const height1 = listHeight[i]
208-
const height2 = listHeight[i + 1]
209-
if (state.current.scrollY >= height1 && state.current.scrollY < height2) {
210-
return setCodeIndex(i)
184+
raf(() => {
185+
const { listHeight } = state.current
186+
if (!listHeight.length) {
187+
calculateHeight()
211188
}
212-
}
189+
const target = e.target as Element
190+
const { scrollTop } = target
191+
state.current.scrollY = Math.floor(scrollTop)
192+
Taro.getEnv() === 'WEB' && setScrollTop(scrollTop)
193+
if (mode === 'vertical' && sticky) {
194+
setScrollY(Math.floor(scrollTop) > 0 ? 1 : 0)
195+
}
196+
if (scrolling.current) return
197+
198+
const index = listHeight.findIndex(
199+
(height, i) =>
200+
state.current.scrollY >= height &&
201+
state.current.scrollY < (listHeight[i + 1] || Infinity)
202+
)
203+
204+
if (index !== -1 && index !== codeIndex) {
205+
setCodeIndex(index)
206+
}
207+
})
213208
}
214209

215210
const getWrapStyle = useMemo(() => {
@@ -219,28 +214,26 @@ export const Elevator: FunctionComponent<
219214
}, [height])
220215

221216
useEffect(() => {
222-
if (listview.current) {
223-
nextTick(() => {
224-
setListGroup()
225-
})
226-
}
227-
}, [listview])
217+
nextTick(() => {
218+
calculateHeight()
219+
})
220+
}, [])
228221

229222
return (
230223
<div
231-
className={`${classPrefix} ${className} ${classPrefix}-${mode} ${classPrefix}-${uuid}`}
224+
className={`${classPrefix} ${className} ${classPrefix}-${mode} `}
225+
id={`${classPrefix}-${uuid}`}
232226
style={style}
233227
{...rest}
234228
>
235229
<View className={`${classPrefix}-list`} style={getWrapStyle}>
236230
<ScrollView
237231
scrollTop={scrollTop}
238232
scrollY
239-
scrollWithAnimation
233+
enhanced
234+
scrollWithAnimation={false}
240235
scrollAnchoring
241236
className={`${classPrefix}-list-inner`}
242-
type="list"
243-
ref={listview}
244237
onScroll={listViewScroll}
245238
onTouchStart={(e) => {
246239
scrolling.current = false

src/packages/elevator/elevator.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ export interface ElevatorProps extends BasicComponent {
1919
list: any[]
2020
sticky: boolean
2121
spaceHeight: number
22-
titleHeight: number
2322
showKeys: boolean
2423
onItemClick: (key: string, item: ElevatorData) => void
2524
onIndexClick: (key: string) => void
@@ -31,8 +30,7 @@ const defaultProps = {
3130
floorKey: 'title',
3231
list: [] as any[],
3332
sticky: false,
34-
spaceHeight: 23,
35-
titleHeight: 35,
33+
spaceHeight: 18,
3634
showKeys: true,
3735
} as ElevatorProps
3836
interface ElevatorData {
@@ -50,7 +48,6 @@ export const Elevator: FunctionComponent<
5048
list,
5149
sticky,
5250
spaceHeight,
53-
titleHeight,
5451
showKeys,
5552
className,
5653
style,

0 commit comments

Comments
 (0)