@minix-iot/ui
Version:
基于Vue的移动端轻量级UI组件库
170 lines (162 loc) • 4.91 kB
JSX
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>
)
}
}