Blame view

node_modules/uview-ui/components/u-index-list/u-index-list.vue 7.98 KB
c7add6cf   “wangming”   初始版本开发完毕
1
  <template>
25852764   unknown   s
2
3
4
  	<!-- 支付宝小程序使用$u.getRect()获取组件的根元素尺寸,所以在外面套一个"壳" -->
  	<view>
  		<view class="u-index-bar">
c7add6cf   “wangming”   初始版本开发完毕
5
  			<slot />
25852764   unknown   s
6
7
8
9
10
11
  			<view v-if="showSidebar" class="u-index-bar__sidebar" @touchstart.stop.prevent="onTouchMove" @touchmove.stop.prevent="onTouchMove"
  			 @touchend.stop.prevent="onTouchStop" @touchcancel.stop.prevent="onTouchStop">
  				<view v-for="(item, index) in indexList" :key="index" class="u-index-bar__index" :style="{zIndex: zIndex + 1, color: activeAnchorIndex === index ? activeColor : ''}"
  				 :data-index="index">
  					{{ item }}
  				</view>
c7add6cf   “wangming”   初始版本开发完毕
12
  			</view>
25852764   unknown   s
13
14
15
16
  			<view class="u-indexed-list-alert" v-if="touchmove && indexList[touchmoveIndex]" :style="{
  				zIndex: alertZIndex
  			}">
  				<text>{{indexList[touchmoveIndex]}}</text>
c7add6cf   “wangming”   初始版本开发完毕
17
18
  			</view>
  		</view>
c7add6cf   “wangming”   初始版本开发完毕
19
20
21
22
  	</view>
  </template>
  
  <script>
25852764   unknown   s
23
24
25
26
  	var indexList = function() {
  		var indexList = [];
  		var charCodeOfA = 'A'.charCodeAt(0);
  		for (var i = 0; i < 26; i++) {
c7add6cf   “wangming”   初始版本开发完毕
27
28
29
  			indexList.push(String.fromCharCode(charCodeOfA + i));
  		}
  		return indexList;
25852764   unknown   s
30
31
  	};
  
c7add6cf   “wangming”   初始版本开发完毕
32
  	/**
25852764   unknown   s
33
34
35
36
37
38
39
40
41
42
43
44
  	 * indexList 索引列表
  	 * @description 通过折叠面板收纳内容区域,搭配<u-index-anchor>使用
  	 * @tutorial https://www.uviewui.com/components/indexList.html#indexanchor-props
  	 * @property {Number String} scroll-top 当前滚动高度,自定义组件无法获得滚动条事件,所以依赖接入方传入
  	 * @property {Array} index-list 索引字符列表,数组(默认A-Z
  	 * @property {Number String} z-index 锚点吸顶时的层级(默认965
  	 * @property {Boolean} sticky 是否开启锚点自动吸顶(默认true
  	 * @property {Number String} offset-top 锚点自动吸顶时与顶部的距离(默认0
  	 * @property {String} highlight-color 锚点和右边索引字符高亮颜色(默认#2979ff
  	 * @event {Function} select 选中右边索引字符时触发
  	 * @example <u-index-list :scrollTop="scrollTop"></u-index-list>
  	 */
c7add6cf   “wangming”   初始版本开发完毕
45
  	export default {
25852764   unknown   s
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  		name: "u-index-list",
  		props: {
  			sticky: {
  				type: Boolean,
  				default: true
  			},
  			zIndex: {
  				type: [Number, String],
  				default: ''
  			},
  			scrollTop: {
  				type: [Number, String],
  				default: 0,
  			},
  			offsetTop: {
  				type: [Number, String],
  				default: 0
  			},
  			indexList: {
  				type: Array,
  				default () {
  					return indexList()
  				}
  			},
  			activeColor: {
  				type: String,
  				default: '#2979ff'
  			}
  		},
  		created() {
  			// #ifdef H5
  			this.stickyOffsetTop = this.offsetTop ? uni.upx2px(this.offsetTop) : 44;
  			// #endif
  			// #ifndef H5
  			this.stickyOffsetTop = this.offsetTop ? uni.upx2px(this.offsetTop) : 0;
  			// #endif
  			// 只能在created生命周期定义children,如果在data定义,会因为循环引用而报错
  			this.children = [];
c7add6cf   “wangming”   初始版本开发完毕
84
  		},
c7add6cf   “wangming”   初始版本开发完毕
85
86
  		data() {
  			return {
25852764   unknown   s
87
88
89
90
91
  				activeAnchorIndex: 0,
  				showSidebar: true,
  				// children: [],
  				touchmove: false,
  				touchmoveIndex: 0,
c7add6cf   “wangming”   初始版本开发完毕
92
93
94
  			}
  		},
  		watch: {
25852764   unknown   s
95
96
  			scrollTop() {
  				this.updateData()
c7add6cf   “wangming”   初始版本开发完毕
97
98
  			}
  		},
25852764   unknown   s
99
100
101
102
103
  		computed: {
  			// 弹出toast的z-index值
  			alertZIndex() {
  				return this.$u.zIndex.toast;
  			}
c7add6cf   “wangming”   初始版本开发完毕
104
105
  		},
  		methods: {
25852764   unknown   s
106
107
108
109
110
111
112
113
  			updateData() {
  				this.timer && clearTimeout(this.timer);
  				this.timer = setTimeout(() => {
  					this.showSidebar = !!this.children.length;
  					this.setRect().then(() => {
  						this.onScroll();
  					});
  				}, 0);
c7add6cf   “wangming”   初始版本开发完毕
114
  			},
25852764   unknown   s
115
116
117
118
119
120
  			setRect() {
  				return Promise.all([
  					this.setAnchorsRect(),
  					this.setListRect(),
  					this.setSiderbarRect()
  				]);
c7add6cf   “wangming”   初始版本开发完毕
121
  			},
25852764   unknown   s
122
123
124
125
126
127
128
129
130
  			setAnchorsRect() {
  				return Promise.all(this.children.map((anchor, index) => anchor
  					.$uGetRect('.u-index-anchor-wrapper')
  					.then((rect) => {
  						Object.assign(anchor, {
  							height: rect.height,
  							top: rect.top
  						});
  					})));
c7add6cf   “wangming”   初始版本开发完毕
131
  			},
25852764   unknown   s
132
133
134
135
136
137
138
  			setListRect() {
  				return this.$uGetRect('.u-index-bar').then((rect) => {
  					Object.assign(this, {
  						height: rect.height,
  						top: rect.top + this.scrollTop
  					});
  				});
c7add6cf   “wangming”   初始版本开发完毕
139
  			},
25852764   unknown   s
140
141
142
143
144
145
146
  			setSiderbarRect() {
  				return this.$uGetRect('.u-index-bar__sidebar').then(rect => {
  					this.sidebar = {
  						height: rect.height,
  						top: rect.top
  					};
  				});
c7add6cf   “wangming”   初始版本开发完毕
147
  			},
25852764   unknown   s
148
149
150
151
152
153
154
155
156
157
158
159
  			getActiveAnchorIndex() {
  				const {
  					children
  				} = this;
  				const {
  					sticky
  				} = this;
  				for (let i = this.children.length - 1; i >= 0; i--) {
  					const preAnchorHeight = i > 0 ? children[i - 1].height : 0;
  					const reachTop = sticky ? preAnchorHeight : 0;
  					if (reachTop >= children[i].top) {
  						return i;
c7add6cf   “wangming”   初始版本开发完毕
160
  					}
25852764   unknown   s
161
162
  				}
  				return -1;
c7add6cf   “wangming”   初始版本开发完毕
163
  			},
25852764   unknown   s
164
  			onScroll() {
c7add6cf   “wangming”   初始版本开发完毕
165
  				const {
25852764   unknown   s
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  					children = []
  				} = this;
  				if (!children.length) {
  					return;
  				}
  				const {
  					sticky,
  					stickyOffsetTop,
  					zIndex,
  					scrollTop,
  					activeColor
  				} = this;
  				const active = this.getActiveAnchorIndex();
  				this.activeAnchorIndex = active;
  				if (sticky) {
  					let isActiveAnchorSticky = false;
  					if (active !== -1) {
  						isActiveAnchorSticky =
  							children[active].top <= 0;
  					}
  					children.forEach((item, index) => {
  						if (index === active) {
  							let wrapperStyle = '';
  							let anchorStyle = {
  								color: `${activeColor}`
  							};
  							if (isActiveAnchorSticky) {
  								wrapperStyle = {
  									height: `${children[index].height}px`
  								};
  								anchorStyle = {
  									position: 'fixed',
  									top: `${stickyOffsetTop}px`,
  									zIndex: `${zIndex ? zIndex : this.$u.zIndex.indexListSticky}`,
  									color: `${activeColor}`
  								};
  							}
  							item.active = active;
  							item.wrapperStyle = wrapperStyle;
  							item.anchorStyle = anchorStyle;
  						} else if (index === active - 1) {
  							const currentAnchor = children[index];
  							const currentOffsetTop = currentAnchor.top;
  							const targetOffsetTop = index === children.length - 1 ?
  								this.top :
  								children[index + 1].top;
  							const parentOffsetHeight = targetOffsetTop - currentOffsetTop;
  							const translateY = parentOffsetHeight - currentAnchor.height;
  							const anchorStyle = {
  								position: 'relative',
  								transform: `translate3d(0, ${translateY}px, 0)`,
  								zIndex: `${zIndex ? zIndex : this.$u.zIndex.indexListSticky}`,
  								color: `${activeColor}`
  							};
  							item.active = active;
  							item.anchorStyle = anchorStyle;
  						} else {
  							item.active = false;
  							item.anchorStyle = '';
  							item.wrapperStyle = '';
  						}
  					});
c7add6cf   “wangming”   初始版本开发完毕
228
229
  				}
  			},
25852764   unknown   s
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  			onTouchMove(event) {
  				this.touchmove = true;
  				const sidebarLength = this.children.length;
  				const touch = event.touches[0];
  				const itemHeight = this.sidebar.height / sidebarLength;
  				let clientY = 0;
  				clientY = touch.clientY;
  				let index = Math.floor((clientY - this.sidebar.top) / itemHeight);
  				if (index < 0) {
  					index = 0;
  				} else if (index > sidebarLength - 1) {
  					index = sidebarLength - 1;
  				}
  				this.touchmoveIndex = index;
  				this.scrollToAnchor(index);
c7add6cf   “wangming”   初始版本开发完毕
245
  			},
25852764   unknown   s
246
247
248
  			onTouchStop() {
  				this.touchmove = false;
  				this.scrollToAnchorIndex = null;
c7add6cf   “wangming”   初始版本开发完毕
249
  			},
25852764   unknown   s
250
251
252
  			scrollToAnchor(index) {
  				if (this.scrollToAnchorIndex === index) {
  					return;
c7add6cf   “wangming”   初始版本开发完毕
253
  				}
25852764   unknown   s
254
255
256
257
258
259
260
261
262
263
264
265
  				this.scrollToAnchorIndex = index;
  				const anchor = this.children.find((item) => item.index === this.indexList[index]);
  				if (anchor) {
  					this.$emit('select', anchor.index);
  					uni.pageScrollTo({
  						duration: 0,
  						scrollTop: anchor.top + this.scrollTop
  					});
  				}
  			}
  		}
  	};
c7add6cf   “wangming”   初始版本开发完毕
266
267
268
  </script>
  
  <style lang="scss" scoped>
25852764   unknown   s
269
270
271
272
273
  	@import "../../libs/css/style.components.scss";
  	
  	.u-index-bar {
  		position: relative
  	}
c7add6cf   “wangming”   初始版本开发完毕
274
  
25852764   unknown   s
275
276
277
278
279
280
281
282
283
284
285
  	.u-index-bar__sidebar {
  		position: fixed;
  		top: 50%;
  		right: 0;
  		@include vue-flex;
  		flex-direction: column;
  		text-align: center;
  		transform: translateY(-50%);
  		user-select: none;
  		z-index: 99;
  	}
c7add6cf   “wangming”   初始版本开发完毕
286
  
25852764   unknown   s
287
288
289
290
291
292
  	.u-index-bar__index {
  		font-weight: 500;
  		padding: 8rpx 18rpx;
  		font-size: 22rpx;
  		line-height: 1
  	}
c7add6cf   “wangming”   初始版本开发完毕
293
  
25852764   unknown   s
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
  	.u-indexed-list-alert {
  		position: fixed;
  		width: 120rpx;
  		height: 120rpx;
  		right: 90rpx;
  		top: 50%;
  		margin-top: -60rpx;
  		border-radius: 24rpx;
  		font-size: 50rpx;
  		color: #fff;
  		background-color: rgba(0, 0, 0, 0.65);
  		@include vue-flex;
  		justify-content: center;
  		align-items: center;
  		padding: 0;
  		z-index: 9999999;
  	}
c7add6cf   “wangming”   初始版本开发完毕
311
  
25852764   unknown   s
312
313
  	.u-indexed-list-alert text {
  		line-height: 50rpx;
c7add6cf   “wangming”   初始版本开发完毕
314
315
  	}
  </style>