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