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