New file |
| | |
| | | <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> |