下面先把列表滚动的组件代码贴出来。
wxml代码如下:
<view class="c-alphabet-nav" style="height: {{ height }}"> <view wx:if="{{ list.length }}"> <scroll-view bindscroll="listScroll" scroll-with-animation scroll-top="{{ scrollTo }}" scroll-y class="wrap-scroll"> <view class="list" wx:for="{{ list }}" wx:key="item.alphabet" id="{{ item.alphabet }}"> <view class="list-title"> <text>{{ item.alphabet }}</text> </view> <view class="list-item" wx:for="{{ item.data }}" wx:for-item="it" wx:key="it" bindtouchstart="tapItem" data-itemInfo="{{ it }}"> <text>{{ it }}</text> </view> </view> </scroll-view> <view class="alphaNavWrap" wx:if="{{ alphaNavFlag }}"> <view class="alphaNav" capture-bind:touchmove="touchmoveHandle" bindtouchend="touchendHandle"> <view wx:for="{{ list }}" wx:key="item.alphabet" class="'alphabet' {{ currentAlpha === item.alphabet ? 'active': '' }}" bindtouchstart="touchstartHandle" data-alpha="{{item.alphabet}}"> {{ item.alphabet }} <view wx:if="{{ moveFlag && currentAlpha === item.alphabet }}" class="sign">{{ item.alphabet }}</view> </view> </view> </view> </view> <view wx:if="{{ !loading && !list.length }}" class="nodata"> <text>暂无数据</text> </view> <view wx:if="{{ loading }}" class="loading"> <text>loading...</text> </view> </view>
wxss代码如下:
.c-alphabet-nav { position: relative; } /*滚动区样式*/ .c-alphabet-nav>view { height: 100%; } .c-alphabet-nav .wrap-scroll { height: 100%; border-top: 1px solid #ddd; } .c-alphabet-nav .list .list-title{ height: 40px; line-height: 40px; padding: 0 20rpx; } .c-alphabet-nav .list .list-item { position: relative; height: 40px; line-height: 40px; background-color: #fff; } .c-alphabet-nav .list .list-item text { display: block; font-size: 14px; padding: 0 20rpx; } .c-alphabet-nav .list .list-item:after { content: ''; display: block; width: 100%; height: 1px; bottom: 0; left: 0; position: absolute; background-color: #d9d9d9; } .c-alphabet-nav .loading, .c-alphabet-nav .nodata { text-align: center; padding-top: 100rpx; font-size: 28rpx; } /*字母导航区样式*/ .alphaNavWrap { width: 20px; height: 100%; position: absolute; top: 0; right: 14rpx; display: flex; align-items: center; } .c-alphabet-nav .alphaNav { font-size: 26rpx; } .c-alphabet-nav .alphaNav .alphabet { width: 40rpx; height: 40rpx; line-height: 40rpx; text-align: center; padding-right: 6rpx; box-sizing: border-box; } .c-alphabet-nav .alphaNav .alphabet.active { background-color: rgba(6, 6, 6, 0.3); border-radius: 50%; } .c-alphabet-nav .alphaNav .sign { position: absolute; font-size: 40rpx; left: -200rpx; top: -30rpx; width: 100rpx; height: 100rpx; text-align: center; line-height: 100rpx; border-radius: 50%; background-color: #ddd; display: none; } .c-alphabet-nav .alphaNav .sign:after { content: ''; display: block; width: 0; height: 0; border-left: 84rpx solid #ddd; border-top: 50rpx solid transparent; border-bottom: 50rpx solid transparent; position: absolute; right: -46rpx; top: 1rpx; z-index: -1; } .c-alphabet-nav .alphaNav .alphabet.active .sign { display: block; }
js文件如下
Component({ properties: { loading: { type: Boolean, value: false }, height: { type: String, value: '80vh' }, list: { type: Array, observer (list) { if (list.length) { try { const res = wx.getSystemInfoSync(); this.setData({windowHeight: res.windowHeight}) } catch (e) { console.error(e) } const query = this.createSelectorQuery(); query.select('.wrap-scroll').boundingClientRect((rect) => { this.data.scrollviewHeight = rect.height }); if (this.data.alphaNavFlag) { query.select('.alphaNav').boundingClientRect((rect) => { this.data.alphaNavPageY = Math.floor(rect.top); this.data.alphaNavItemHeight = rect.height / this.data.list.length }); } query.select('.list-item').boundingClientRect((rect) => { let tempArray = []; this.data.list.forEach((item, i) => { let tempObj = {}; tempObj.alphabet = item.alphabet; tempObj.height = (item.data.length + 1) * rect.height; if (i) tempObj.height += tempArray[i - 1].height; // 高度累加 tempArray.push(tempObj); }); this.setData({'itemHeight': tempArray}); // 当滚动区滑块滑动到底部时,滚动条的位置 let pageHeight = tempArray[tempArray.length - 1].height; // 滚动区内容总高度 let maxScrollTop = pageHeight - this.data.scrollviewHeight; if (maxScrollTop > 0) { this.setData({'maxScrollTop': maxScrollTop}); this.setData({ 'alphaNavFlag': true }) } else { this.setData({ 'alphaNavFlag': false }) } }); setTimeout(() => { query.exec(); }) } } } }, data: { alphaNavFlag: false, currentAlpha: 'A', // 列表当前滑动到的元素 itemHeight: [], // 列表字母项底部距滚动区文档顶部的高度 scrollTo: 0, // 当前元素项顶部距离滚动区文档顶部的距离 windowHeight: 603, // 设备高度 scrollviewHeight: 0, // 滚动区域高度 alphaNavHeight: 0, // 右侧字母列表高度 down: false, moveFlag: false, maxScrollTop: 0 // 页面滑到底时滚动条距顶部的高度 }, methods: { inputHandle (e) { this.setData({'searchText': e.detail.value}) }, touchmoveHandle (e) { this.setData({ 'moveFlag': true }); const distance = e.touches[0].pageY - this.data.alphaNavPageY; const currentAlpha = this.data.list[Math.floor(distance / this.data.alphaNavItemHeight)].alphabet; this.setData({ 'currentAlpha': currentAlpha }) this.goScroll(); }, touchendHandle () { this.setData({ 'moveFlag': false }); }, goScroll () { let parameter = { 'scrollTo': 0, 'currentAlpha': this.data.currentAlpha }; let { currentAlpha, list, itemHeight, maxScrollTop } = this.data; if (currentAlpha !== list[0].alphabet) { itemHeight.forEach((item, i) => { if (item.alphabet === currentAlpha) { parameter.scrollTo = itemHeight[i - 1].height; this.setData({'down': itemHeight[i - 1].height > maxScrollTop}); } }) } this.setData(parameter); }, tapItem (e) { this.triggerEvent('tapItem', e.currentTarget.dataset) }, touchstartHandle (e) { this.setData({'currentAlpha': e.target.dataset.alpha}); this.goScroll(); }, listScroll (e) { if (this.data.timeId) { clearTimeout(this.data.timeId); } this.data.timeId = setTimeout(() => { let currentScrollTop = e.detail.scrollTop; // 滚动条距顶部的实时距离 const { itemHeight, maxScrollTop, down } = this.data; if (currentScrollTop >= maxScrollTop && down) { this.setData({'down': false}); return } for (let i = 0; i < itemHeight.length; i++) { if (currentScrollTop < itemHeight[i].height) { this.setData({ 'currentAlpha': itemHeight[i].alphabet }); break } } }, 100); }, } });
转载于:https://www.cnblogs.com/qddyh/p/11160950.html