u-scroll-list.vue
6.0 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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
<template>
<view
class="u-scroll-list"
ref="u-scroll-list"
>
<!-- #ifdef APP-NVUE -->
<!-- nvue使用bindingX实现,以得到更好的性能 -->
<scroller
class="u-scroll-list__scroll-view"
ref="u-scroll-list__scroll-view"
scroll-direction="horizontal"
:show-scrollbar="false"
:offset-accuracy="1"
@scroll="nvueScrollHandler"
>
<view class="u-scroll-list__scroll-view__content">
<slot />
</view>
</scroller>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<!-- #ifdef MP-WEIXIN || APP-VUE || H5 || MP-QQ -->
<!-- 以上平台,支持wxs -->
<scroll-view
class="u-scroll-list__scroll-view"
scroll-x
@scroll="wxs.scroll"
@scrolltoupper="wxs.scrolltoupper"
@scrolltolower="wxs.scrolltolower"
:data-scrollWidth="scrollWidth"
:data-barWidth="$u.getPx(indicatorBarWidth)"
:data-indicatorWidth="$u.getPx(indicatorWidth)"
:show-scrollbar="false"
:upper-threshold="0"
:lower-threshold="0"
>
<!-- #endif -->
<!-- #ifndef APP-NVUE || MP-WEIXIN || H5 || APP-VUE || MP-QQ -->
<!-- 非以上平台,只能使用普通js实现 -->
<scroll-view
class="u-scroll-list__scroll-view"
scroll-x
@scroll="scrollHandler"
@scrolltoupper="scrolltoupperHandler"
@scrolltolower="scrolltolowerHandler"
:show-scrollbar="false"
:upper-threshold="0"
:lower-threshold="0"
>
<!-- #endif -->
<view class="u-scroll-list__scroll-view__content">
<slot />
</view>
</scroll-view>
<!-- #endif -->
<view
class="u-scroll-list__indicator"
v-if="indicator"
:style="[$u.addStyle(indicatorStyle)]"
>
<view
class="u-scroll-list__indicator__line"
:style="[lineStyle]"
>
<view
class="u-scroll-list__indicator__line__bar"
:style="[barStyle]"
ref="u-scroll-list__indicator__line__bar"
></view>
</view>
</view>
</view>
</template>
<script
src="./scrollWxs.wxs"
module="wxs"
lang="wxs"
></script>
<script>
/**
* scrollList 横向滚动列表
* @description 该组件一般用于同时展示多个商品、分类的场景,也可以完成左右滑动的列表。
* @tutorial https://www.uviewui.com/components/scrollList.html
* @property {String | Number} indicatorWidth 指示器的整体宽度 (默认 50 )
* @property {String | Number} indicatorBarWidth 滑块的宽度 (默认 20 )
* @property {Boolean} indicator 是否显示面板指示器 (默认 true )
* @property {String} indicatorColor 指示器非激活颜色 (默认 '#f2f2f2' )
* @property {String} indicatorActiveColor 指示器的激活颜色 (默认 '#3c9cff' )
* @property {String | Object} indicatorStyle 指示器样式,可通过bottom,left,right进行定位
* @event {Function} left 滑动到左边时触发
* @event {Function} right 滑动到右边时触发
* @example
*/
// #ifdef APP-NVUE
const dom = uni.requireNativePlugin('dom')
import nvueMixin from "./nvue.js"
// #endif
import props from './props.js';
export default {
name: 'u-scroll-list',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
// #ifdef APP-NVUE
mixins: [uni.$u.mpMixin, uni.$u.mixin, nvueMixin, props],
// #endif
data() {
return {
scrollInfo: {
scrollLeft: 0,
scrollWidth: 0
},
scrollWidth: 0
}
},
computed: {
// 指示器为线型的样式
barStyle() {
const style = {}
// #ifndef APP-NVUE || MP-WEIXIN || H5 || APP-VUE || MP-QQ
// 此为普通js方案,只有在非nvue和不支持wxs方案的端才使用、
// 此处的计算理由为:scroll-view的滚动距离与目标滚动距离(scroll-view的实际宽度减去包裹元素的宽度)之比,等于滑块当前移动距离与总需
// 滑动距离(指示器的总宽度减去滑块宽度)的比值
const scrollLeft = this.scrollInfo.scrollLeft,
scrollWidth = this.scrollInfo.scrollWidth,
barAllMoveWidth = this.indicatorWidth - this.indicatorBarWidth
const x = scrollLeft / (scrollWidth - this.scrollWidth) * barAllMoveWidth
style.transform = `translateX(${ x }px)`
// #endif
// 设置滑块的宽度和背景色,是每个平台都需要的
style.width = uni.$u.addUnit(this.indicatorBarWidth)
style.backgroundColor = this.indicatorActiveColor
return style
},
lineStyle() {
const style = {}
// 指示器整体的样式,需要设置其宽度和背景色
style.width = uni.$u.addUnit(this.indicatorWidth)
style.backgroundColor = this.indicatorColor
return style
}
},
mounted() {
this.init()
},
methods: {
init() {
this.getComponentWidth()
},
// #ifndef APP-NVUE || MP-WEIXIN || H5 || APP-VUE || MP-QQ
// scroll-view触发滚动事件
scrollHandler(e) {
this.scrollInfo = e.detail
},
scrolltoupperHandler() {
this.scrollEvent('left')
this.scrollInfo.scrollLeft = 0
},
scrolltolowerHandler() {
this.scrollEvent('right')
// 在普通js方案中,滚动到右边时,通过设置this.scrollInfo,模拟出滚动到右边的情况
// 因为上方是用过computed计算的,设置后,会自动调整滑块的位置
this.scrollInfo.scrollLeft = uni.$u.getPx(this.indicatorWidth) - uni.$u.getPx(this.indicatorBarWidth)
},
// #endif
//
scrollEvent(status) {
this.$emit(status)
},
// 获取组件的宽度
async getComponentWidth() {
// 延时一定时间,以获取dom尺寸
await uni.$u.sleep(30)
// #ifndef APP-NVUE
this.$uGetRect('.u-scroll-list').then(size => {
this.scrollWidth = size.width
})
// #endif
// #ifdef APP-NVUE
const ref = this.$refs['u-scroll-list']
ref && dom.getComponentRect(ref, (res) => {
this.scrollWidth = res.size.width
})
// #endif
},
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-scroll-list {
padding-bottom: 10px;
&__scroll-view {
@include flex;
&__content {
@include flex;
}
}
&__indicator {
@include flex;
justify-content: center;
margin-top: 15px;
&__line {
width: 60px;
height: 4px;
border-radius: 100px;
overflow: hidden;
&__bar {
width: 20px;
height: 4px;
border-radius: 100px;
}
}
}
}
</style>