UNPKG

@minix-iot/ui

Version:

基于Vue的移动端轻量级UI组件库

170 lines (162 loc) 4.91 kB
import { Namespace } from '../../utils/namespace' import { Touch } from '../../utils/touch' import { DOMExtension } from '../../utils/extensions/dom' const namespace = Namespace.Create('pull-refresh') export default { name:namespace.name, props:{ distanceToRefresh: { type: Number, default: 50 }, loading: { type: Boolean, default: false }, finished: { type: Boolean, default: false } }, data(){ return { status: 'normal', isReachTop: false, touch: Touch.Create() } }, computed:{ cls(){ return namespace.derive() }, containerCls(){ return namespace.derive('container') }, infoCls(){ return namespace.derive('info') }, viewerCls(){ return namespace.derive('viewer') }, containerStyle(){ let distance = this.ease(this.touch.deltaY); if(this.isLoading){ distance = this.distanceToRefresh } return `transform:translateY(${distance}px)`; }, infoStyle(){ return `height:${this.distanceToRefresh}px` }, isPulling(){ return this.status === 'pulling' }, isLoosing(){ return this.status === 'loosing' }, isLoading(){ return this.loading }, isFinished(){ return this.finished }, isTouchable(){ return !this.isLoading } }, methods:{ onTouchStart(e){ if(!this.isTouchable){ return } if (!this.isReachEdge()) { return; } this.touch.start(e) }, onTouchMove(e){ if (!this.isTouchable) { return; } if (!this.isReachEdge()) { return; } if(this.touch.startY === 0 ){ this.touch.start(e) }else{ this.touch.move(e) if(this.touch.deltaY > 0){ DOMExtension.PreventDefault(e) if(this.touch.deltaY < this.distanceToRefresh){ this.status = 'pulling' }else{ this.status = 'loosing' } } } }, onTouchEnd(e){ if(this.touch.deltaY > this.distanceToRefresh){ this.$emit('refresh', e) } this.touch.reset() this.status = 'normal' }, isReachEdge(){ return this.$refs.viewer.scrollTop === 0 }, ease(deltaY) { let distance = deltaY < 0 ? 0 : deltaY; if (distance > this.distanceToRefresh) { if (distance < this.distanceToRefresh * 2) { distance = this.distanceToRefresh + (distance - this.distanceToRefresh) / 2; } else { distance = this.distanceToRefresh * 1.5 + (distance - this.distanceToRefresh * 2) / 4; } } return Math.round(distance); }, }, render(){ const renderPull = ()=>( this.$slots.pull || <div>下拉刷新</div> ) const renderLoading = ()=>( // <div>加载中...</div> this.$slots.loading || <mx-loading type="spinner" size={18}/> ) const renderLoose = ()=>( this.$slots.loose || <div>释放刷新</div> ) const renderFinished = ()=>( this.$slots.finished || <div>- 没有更多内容了 -</div> ) const renderInfo = ()=>( <div class={this.infoCls} style={this.infoStyle}> {!this.isFinished && this.isPulling && renderPull()} {!this.isFinished && this.isLoosing && renderLoose()} {!this.isFinished && this.isLoading && renderLoading()} {this.isFinished && renderFinished()} </div> ) const renderViewer = ()=>( <div ref={'viewer'} class={this.viewerCls}> {this.$slots.default} </div> ) return ( <div class={this.cls}> <div class={this.containerCls} style={this.containerStyle} onTouchstart = {this.onTouchStart} onTouchmove = {this.onTouchMove} onTouchend = {this.onTouchEnd} onTouchcancel = {this.onTouchEnd} > {renderInfo()} {renderViewer()} </div> </div> ) } }