123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- <template>
- <scroll-view
- :lower-threshold="lowerThreshold"
- :refresher-triggered="refresherTriggered"
- :refresher-threshold="1"
- :refresher-enabled="refresh"
- :scroll-top="scrollTop"
- refresher-background="rgba(0,0,0,0)"
- refresher-default-style="none"
- scroll-y
- scroll-with-animation
- class="wk-scroll-view"
- @refresherpulling="refresherpulling"
- @refresherrefresh="refresherrefresh"
- @refresherrestore="refresherRestoreOrAbort"
- @refresherabort="refresherRestoreOrAbort"
- @scroll="handleScroll"
- @scrolltoupper="handleScrollUpper"
- @scrolltolower="handleLoadMore">
- <!-- 刷新提示 -->
- <uni-load-more
- v-if="showRefresh && refresh"
- :status="status"
- :content-text="contentText"
- icon-type="circle"
- class="wk-scroll-view-top" />
- <!-- 内容 -->
- <slot />
- <!-- 暂无数据 -->
- <!-- #ifdef MP-WEIXIN -->
- <view
- v-if="showNoData && showEmpty"
- :style="{backgroundImage: bgUrl('images/no_data.png')}"
- class="no-data">
- 暂无数据
- </view>
- <!-- #endif -->
- <!-- #ifndef MP-WEIXIN -->
- <view
- v-if="!$slots.default && showEmpty"
- :style="{backgroundImage: bgUrl('images/no_data.png')}"
- class="no-data">
- 暂无数据
- </view>
- <!-- #endif -->
- <!-- 加载更多提示 -->
- <uni-load-more
- v-if="showLoadMore"
- :status="status"
- :content-text="contentText"
- icon-type="circle"
- class="wk-scroll-view-bottom" />
- </scroll-view>
- </template>
- <script>
- /**
- * 上拉加载下拉刷新控件
- * @desc 容器必须有一个固定的高度
- * props:
- * {string} | status | loading 状态; 可选项:more(loading前)、loading(loading中)、noMore(没有更多了)
- * {number} | lowerThreshold | 距底部/右边多远时(单位px),触发加载更多事件(默认20)
- * {number} | scrollTop | 设置竖向滚动条位置
- * {boolean} | refresh | 是否开启下拉刷新,默认开启
- * {boolean} | loadMore | 是否开启上拉加载,默认开启
- * {boolean} | showEmpty | 列表无数据时是否显示无数据提示,默认true显示
- * event
- * refresh | 下拉刷新时触发 | 回调:null
- * loadmore | 上拉加载时触发 | 回调:null
- * scroll | 滚动时触发 | 回调:evt
- *
- * @author yxk
- */
- export default {
- name: 'WkScrollView',
- props: {
- status: { // loading 状态
- type: String,
- default: 'loading',
- validator: value => {
- return ['more', 'loading', 'noMore', ''].includes(value)
- }
- },
- lowerThreshold: {
- type: Number,
- default: 20
- },
- refresh: {
- type: Boolean,
- default: true
- },
- loadMore: {
- type: Boolean,
- default: true
- },
- showEmpty: {
- type: Boolean,
- default: true
- },
- scrollTop: {
- type: Number,
- default: 0
- }
- },
- data() {
- return {
- showRefresh: false,
- showLoadMore: false,
- refresherTriggered: false, // 设置当前下拉刷新状态
- restoreFlag: false,
- showNoData: false
- }
- },
- computed: {
- contentText() {
- if (this.showRefresh) {
- return {
- contentdown: '下拉刷新',
- contentrefresh: '正在刷新...',
- contentnomore: ''
- }
- }
- return {
- contentdown: '加载更多',
- contentrefresh: '正在加载中...',
- contentnomore: '已经到底啦~'
- }
- }
- },
- watch: {
- status: {
- handler(val) {
- if (val === 'loading') {
- this.refresherTriggered = true
- } else {
- this.refresherTriggered = 'restore'
- this.$nextTick(() => {
- this.refresherTriggered = false
- })
- this.showRefresh = false
- }
- this.calcNoData()
- },
- immediate: true
- }
- },
- activated() {
- console.log('activated')
- this.calcNoData()
- },
- mounted() {
- console.log('mounted')
- this.calcNoData()
- },
- methods: {
- bgUrl(val) {
- return `url(${this.$static(val)})`
- },
- calcNoData() {
- // #ifdef MP-WEIXIN
- this.$nextTick(() => {
- const old = !this.showNoData
- this.showNoData = old
- this.$nextTick(() => {
- this.showNoData = Boolean(!this.$children || this.$children.length === 0)
- // console.log('showNoData: ', this.showNoData)
- })
- })
- // #endif
- },
- /**
- * 自定义下拉刷新控件被下拉
- */
- refresherpulling() {
- // console.log('refresherpulling run')
- },
- /**
- * 自定义下拉刷新被触发
- */
- refresherrefresh(e) {
- // console.log('refresherrefresh run', e)
- if (this.status !== 'loading') {
- this.showRefresh = true
- this.refresherTriggered = true
- this.handleRefresh()
- }
- },
- /**
- * 自定义下拉刷新被复位/中止
- */
- refresherRestoreOrAbort(e) {
- // console.log('refresherRestoreOrAbort')
- if (!this.restoreFlag) {
- this.refresherTriggered = 'restore'
- this.restoreFlag = true
- }
- this.$nextTick(function() {
- this.refresherTriggered = false
- })
- this.showRefresh = false
- },
- /**
- * 滚动到顶部
- */
- handleScrollUpper() {
- // console.log('handleScrollUpper')
- this.restoreFlag = false
- this.refresherTriggered = 'restore'
- this.$nextTick(function() {
- this.refresherTriggered = false
- })
- },
- /**
- * 监听滚动
- * @param {Object} evt
- */
- handleScroll(evt) {
- this.restoreFlag = false
- this.$emit('scroll', evt)
- // evt.detail.scrollTop
- },
- /**
- * 触发下拉刷新
- */
- handleRefresh() {
- if (this.timer) {
- clearTimeout(this.timer)
- this.timer = null
- }
- // 处理 refresherrefresh 事件被触发多次问题,节流
- this.timer = setTimeout(() => {
- this.$emit('refresh')
- clearTimeout(this.timer)
- this.timer = null
- }, 30)
- },
- /**
- * 触发上拉加载
- */
- handleLoadMore() {
- if (!this.loadMore) return
- // console.log('loadmore')
- this.showLoadMore = true
- if (this.status === 'noMore') return
- this.$emit('loadmore')
- }
- }
- }
- </script>
- <style scoped lang="scss">
- .wk-scroll-view {
- position: relative;
- width: 100%;
- height: 100%;
- overflow: auto;
- }
- .no-data {
- width: 100%;
- text-align: center;
- font-size: 26rpx;
- color: #BBBBBB;
- background-position: center 200rpx;
- background-repeat: no-repeat;
- background-size: 36%;
- padding-top: 520rpx;
- }
- </style>
|