|
|
- <template>
- <view class="yingbing-scroller"
- :refreshState="refreshState" :change:refreshState="pulldownwxs.refreshStateWatcher"
- :pulldownable="pulldownable" :change:pulldownable="pulldownwxs.pulldownableWatcher"
- :pullupable="pullupable" :change:pullupable="pulldownwxs.pullupableWatcher"
- @touchstart="pulldownwxs.touchstart"
- @touchmove="pulldownwxs.touchmove"
- @touchend="pulldownwxs.touchend"
- @touchcancel="pulldownwxs.touchcancel">
- <view class="yingbing-scroller-wrapper">
- <view class="yingbing-scroller-refresh">
- <refresh-loading size="30" :visible="pulldownStatus == 'end' ? false : Boolean(pulldownStatus)" :color="loadingColor"></refresh-loading>
- <text class="yingbing-scroller-refresh-text" :style="{color: loadingColor}">{{ pulldownText }}</text>
- </view>
- <view class="yingbing-scroll">
- <scroll-view
- scroll-anchoing
- class="yingbing-scroll-view"
- scroll-y
- :refresher-enabled="false"
- :scroll-into-view="scrollIntoViewId"
- :scroll-with-animation="scrollWithAnimation"
- :show-scrollbar="false"
- :scroll-top="scrollTop"
- :lower-threshold="100"
- @scroll="handleScroll" @scrolltolower="handleScrolltolower"
- @scrolltoupper="handleScrolltoupper">
- <view :id="'yingbing-scroll-item_' + index" v-for="(item, index) in data" :key="item.index + '_' + item.current">
- <!-- #ifdef MP -->
- <slot :name="'wx:' + index"></slot>
- <!-- #endif -->
- <!-- #ifndef MP -->
- <slot :item="item" :index="index"></slot>
- <!-- #endif -->
- </view>
- <view class="yingbing-scroller-refresh" v-if="loadmoreable" @tap="handleScrolltolower">
- <refresh-loading size="30" :visible="loadmoreStatus == 'end' ? false : Boolean(loadmoreStatus)" :color="loadingColor"></refresh-loading>
- <text class="yingbing-scroller-refresh-text">{{loadmoreText}}</text>
- </view>
- </scroll-view>
- </view>
- <view class="yingbing-scroller-refresh">
- <refresh-loading size="30" :visible="pullupStatus == 'end' ? false : Boolean(pullupStatus)" :color="loadingColor"></refresh-loading>
- <text class="yingbing-scroller-refresh-text" :style="{color: loadingColor}">{{ pullupText }}</text>
- </view>
- </view>
- </view>
- </template>
-
- <script>
- import RefreshLoading from '../loading/loading.vue'
- const readyHeight = 80
- export default {
- options: {
- addGlobalClass: true,
- virtualHost: true,//将自定义节点设置成虚拟的,更加接近Vue组件的表现。我们不希望自定义组件的这个节点本身可以设置样式、响应 flex 布局等,而是希望自定义组件内部的第一层节点能够响应 flex 布局或者样式由自定义组件本身完全决定
- },
- components: {
- RefreshLoading
- },
- inject: ['getPrevChapterDefaultText', 'getNextChapterDefaultText', 'getChapterReadyText', 'getChapterLoadingText', 'getChapterSuccessText', 'getChapterFailText', 'getPrevChapterEndText', 'getNextChapterEndText'],
- props: {
- data: {
- type: Array,
- default () {
- return new Array
- }
- },
- loadingColor: {
- type: String,
- default: '#333'
- },
- autoplay: {
- type: Boolean,
- default: false
- },
- pulldownable: {
- type: Boolean,
- default: false
- },
- pullupable: {
- type: Boolean,
- default: false
- },
- loadmoreable: {
- type: Boolean,
- default: false
- }
- },
- computed: {
- chapterReadyText () {
- return this.getChapterReadyText()
- },
- chapterLoadingText () {
- return this.getChapterLoadingText()
- },
- chapterSuccessText () {
- return this.getChapterSuccessText()
- },
- chapterFailText () {
- return this.getChapterFailText()
- },
- prevChapterDefaultText () {
- return this.getPrevChapterDefaultText()
- },
- prevChapterEndText() {
- return this.getPrevChapterEndText()
- },
- nextChapterDefaultText() {
- return this.getNextChapterDefaultText()
- },
- nextChapterEndText() {
- return this.getNextChapterEndText()
- },
- pulldownText () {
- return this.pulldownStatus == 'ready' ? this.chapterReadyText : this.pulldownStatus == 'success' ? this.chapterSuccessText : this.pulldownStatus == 'fail' ? this.chapterFailText : this.pulldownStatus == 'end' ? this.prevChapterEndText : this.prevChapterDefaultText
- },
- pullupText () {
- return this.pullupStatus == 'ready' ? this.chapterReadyText : this.pullupStatus == 'success' ? this.chapterSuccessText : this.pullupStatus == 'fail' ? this.chapterFailText : this.pullupStatus == 'end' ? this.nextChapterEndText : this.nextChapterDefaultText
- },
- loadmoreText () {
- return this.loadmoreStatus == 'ready' ? this.chapterLoadingText : this.loadmoreStatus == 'success' ? this.chapterSuccessText : this.loadmoreStatus == 'fail' ? this.chapterFailText : this.loadmoreStatus == 'end' ? this.nextChapterEndText : this.nextChapterDefaultText
- }
- },
- data () {
- return {
- refreshState: '',
- pulldownStatus: '',
- pullupStatus: '',
- loadmoreStatus: '',
- isLoadmore: false,
- scrollIntoViewId: '',
- scrollWithAnimation: false,
- scrollTop: 0,
- scrollTopRecord: 0
- }
- },
- created() {
- this.startAutoplay()
- },
- beforeDestroy() {
- this.stopAutoplay()
- },
- methods: {
- handleScroll (e) {
- this.scrollTopRecord = e.detail.scrollTop
- this.$emit('scroll', e)
- },
- handleScrolltolower (e) {
- if ( !this.loadmoreable || this.isLoadmore || this.loadmoreStatus == 'end' ) return
- this.isLoadmore = true
- this.loadmoreStatus = 'ready'
- this.$emit('loadmore', (state) => {
- this.loadmoreStatus = state
- this.isLoadmore = false
- })
- },
- handleScrolltoupper (e) {
- this.$emit('scrolltoupper', e)
- },
- pulldown () {
- if ( this.pulldownStatus == 'end' ) {
- this.stopRefresh()
- return
- }
- this.$emit('pulldown', (state) => {
- this.pulldownStatus = state
- this.stopRefresh()
- })
- },
- pullup () {
- if ( this.pullupStatus == 'end' ) {
- this.stopRefresh()
- return
- }
- this.$emit('pullup', (state) => {
- this.pullupStatus = state
- this.stopRefresh()
- })
- },
- startPulldown () {
- this.pulldownStatus = 'ready'
- this.refreshState = ''
- this.$nextTick(function () {
- this.refreshState = 'pulldown'
- })
- },
- startPullup () {
- this.pullupStatus = 'ready'
- this.refreshState = ''
- this.$nextTick(function () {
- this.refreshState = 'pullup'
- })
- },
- stopRefresh () {
- this.refreshState = ''
- this.$nextTick(function () {
- this.refreshState = 'stop'
- })
- },
- resetRefresh () {
- this.pulldownStatus = ''
- this.pullupStatus = ''
- this.refreshState = ''
- this.loadmoreState = ''
- this.isLoadmore = false
- },
- scrollToIndex (index, animated = false) {
- this.stopAutoplay()
- this.scrollIntoViewId = ''
- this.scrollWithAnimation = animated
- this.$nextTick(function () {
- this.scrollIntoViewId = 'yingbing-scroll-item_' + index
- this.$nextTick(function () {
- this.scrollWithAnimation = false
- setTimeout(() => {
- this.startAutoplay()
- }, 400)
- })
- })
- },
- getItemRect (index) {
- return new Promise(resolve => {
- uni.createSelectorQuery().in(this).select('#yingbing-scroll-item_' + index).boundingClientRect(data => {
- resolve(data)
- }).exec();
- })
- },
- pullingdown (threshold) {
- if ( this.pulldownStatus != 'end' ) {
- // #ifndef APP-NVUE
- if ( threshold >= readyHeight ) {
- this.pulldownStatus = 'ready'
- } else {
- this.pulldownStatus = 'pull'
- }
- // #endif
- // #ifdef APP-NVUE
- if ( threshold >= 195 ) {
- this.pulldownStatus = 'ready'
- } else {
- this.pulldownStatus = 'pull'
- }
- // #endif
- }
- },
- pullingup (threshold) {
- if ( this.pullupStatus != 'end' ) {
- // #ifndef APP-NVUE
- if ( threshold >= readyHeight ) {
- this.pullupStatus = 'ready'
- } else {
- this.pullupStatus = 'pull'
- }
- // #endif
- // #ifdef APP-NVUE
- if ( threshold >= 195 ) {
- this.pullupStatus = 'ready'
- } else {
- this.pullupStatus = 'pull'
- }
- // #endif
- }
- },
- setScrollTop (top) {
- this.scrollTop = top
- this.scrollTopRecord = top
- },
- startAutoplay () {
- this.stopAutoplay()
- this.scrollTop = this.scrollTopRecord
- if ( this.autoplay && this.data.length > 0 ) {
- this.autoplayTimer = setInterval(() => {
- if ( this.scrollTop - this.scrollTopRecord > 2 ) this.scrollTop = this.scrollTopRecord//如果scrollTop比滚动距离大2像素,说明发生过等待章节加载,需要重新赋值scrollTop真实的滚动距离
- this.scrollTop += 1
- }, 20)
- }
- },
- stopAutoplay () {
- if ( this.autoplayTimer ) {
- clearInterval(this.autoplayTimer)
- this.autoplayTimer = null
- }
- }
- },
- watch: {
- autoplay () {
- this.startAutoplay()
- }
- }
- }
- </script>
- <!-- #ifdef APP-VUE || H5 || MP-WEIXIN || MP-QQ -->
- <script module="pulldownwxs" lang="wxs" src="./pulldown.wxs"></script>
- <!-- #endif -->
-
- <style scoped>
- /* #ifdef APP-VUE || H5 */
- /deep/ .yingbing-scroll-view .uni-scroll-view::-webkit-scrollbar {
- display: none;
- width: 0 !important;
- height: 0 !important;
- -webkit-appearance: none;
- background: transparent;
- }
- /* #endif */
- /* #ifdef MP */
- /deep/ ::-webkit-scrollbar {
- display: none;
- width: 0 !important;
- height: 0 !important;
- -webkit-appearance: none;
- background: transparent;
- }
- /* #endif */
- .yingbing-scroller {
- /* #ifndef APP-NVUE */
- height: 100%;
- /* #endif */
- /* #ifdef APP-NVUE */
- flex: 1;
- /* #endif */
- position: relative;
- overflow: hidden;
- }
- .yingbing-scroller-wrapper {
- height: calc(100% + 160px);
- position: absolute;
- top: -80px;
- left: 0;
- right: 0;
- display: flex;
- flex-direction: column;
- }
- .yingbing-scroller-refresh {
- height: 80px;
- padding: 20px 0;
- box-sizing: border-box;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .yingbing-scroller-refresh-text {
- font-size: 13px;
- margin-left: 10px;
- }
- .yingbing-scroll {
- flex: 1;
- position: relative;
- }
- .yingbing-scroll-view {
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- }
- </style>
|