| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- import { use } from '../utils';
- import { preventDefault } from '../utils/event';
- import { TouchMixin } from '../mixins/touch';
- import { getScrollTop, getScrollEventTarget } from '../utils/scroll';
- import Loading from '../loading';
- const [sfc, bem, t] = use('pull-refresh');
- const TEXT_STATUS = ['pulling', 'loosing', 'success'];
- export default sfc({
- mixins: [TouchMixin],
- props: {
- disabled: Boolean,
- successText: String,
- pullingText: String,
- loosingText: String,
- loadingText: String,
- value: {
- type: Boolean,
- required: true
- },
- successDuration: {
- type: Number,
- default: 500
- },
- animationDuration: {
- type: Number,
- default: 300
- },
- headHeight: {
- type: Number,
- default: 50
- }
- },
- data() {
- return {
- status: 'normal',
- height: 0,
- duration: 0
- };
- },
- computed: {
- untouchable() {
- return this.status === 'loading' || this.status === 'success' || this.disabled;
- }
- },
- watch: {
- value(loading) {
- this.duration = this.animationDuration;
- if (!loading && this.successText) {
- this.status = 'success';
- setTimeout(() => {
- this.setStatus(0);
- }, this.successDuration);
- } else {
- this.setStatus(loading ? this.headHeight : 0, loading);
- }
- }
- },
- mounted() {
- this.scrollEl = getScrollEventTarget(this.$el);
- },
- methods: {
- onTouchStart(event) {
- if (!this.untouchable && this.getCeiling()) {
- this.duration = 0;
- this.touchStart(event);
- }
- },
- onTouchMove(event) {
- if (this.untouchable) {
- return;
- }
- this.touchMove(event);
- if (!this.ceiling && this.getCeiling()) {
- this.duration = 0;
- this.startY = event.touches[0].clientY;
- this.deltaY = 0;
- }
- if (this.ceiling && this.deltaY >= 0) {
- if (this.direction === 'vertical') {
- this.setStatus(this.ease(this.deltaY));
- preventDefault(event);
- }
- }
- },
- onTouchEnd() {
- if (!this.untouchable && this.ceiling && this.deltaY) {
- this.duration = this.animationDuration;
- if (this.status === 'loosing') {
- this.setStatus(this.headHeight, true);
- this.$emit('input', true);
- this.$emit('refresh');
- } else {
- this.setStatus(0);
- }
- }
- },
- getCeiling() {
- this.ceiling = getScrollTop(this.scrollEl) === 0;
- return this.ceiling;
- },
- ease(height) {
- const { headHeight } = this;
- return height < headHeight
- ? height
- : height < headHeight * 2
- ? Math.round(headHeight + (height - headHeight) / 2)
- : Math.round(headHeight * 1.5 + (height - headHeight * 2) / 4);
- },
- setStatus(height, isLoading) {
- this.height = height;
- const status = isLoading
- ? 'loading'
- : height === 0
- ? 'normal'
- : height < this.headHeight
- ? 'pulling'
- : 'loosing';
- if (status !== this.status) {
- this.status = status;
- }
- }
- },
- render(h) {
- const { status } = this;
- const text = this[`${status}Text`] || t(status);
- const style = {
- transition: `${this.duration}ms`,
- transform: this.height ? `translate3d(0,${this.height}px, 0)` : ''
- };
- const Status = this.slots(status) || [
- TEXT_STATUS.indexOf(status) !== -1 && <div class={bem('text')}>{text}</div>,
- status === 'loading' && (
- <div class={bem('loading')}>
- <Loading />
- <span>{text}</span>
- </div>
- )
- ];
- return (
- <div class={bem()}>
- <div
- class={bem('track')}
- style={style}
- onTouchstart={this.onTouchStart}
- onTouchmove={this.onTouchMove}
- onTouchend={this.onTouchEnd}
- onTouchcancel={this.onTouchEnd}
- >
- <div class={bem('head')}>{Status}</div>
- {this.slots()}
- </div>
- </div>
- );
- }
- });
|