import { use } from '../utils'; import Loading from '../loading'; import { on, off } from '../utils/event'; import { getScrollTop, getElementTop, getVisibleHeight, getScrollEventTarget } from '../utils/scroll'; const [sfc, bem, t] = use('list'); export default sfc({ model: { prop: 'loading' }, props: { error: Boolean, loading: Boolean, finished: Boolean, errorText: String, loadingText: String, finishedText: String, immediateCheck: { type: Boolean, default: true }, offset: { type: Number, default: 300 }, direction: { type: String, default: 'down' } }, mounted() { this.scroller = getScrollEventTarget(this.$el); this.handler(true); if (this.immediateCheck) { this.$nextTick(this.check); } }, destroyed() { this.handler(false); }, activated() { this.handler(true); }, deactivated() { this.handler(false); }, watch: { loading() { this.$nextTick(this.check); }, finished() { this.$nextTick(this.check); } }, methods: { check() { if (this.loading || this.finished || this.error) { return; } const el = this.$el; const { scroller } = this; const scrollerHeight = getVisibleHeight(scroller); /* istanbul ignore next */ if ( !scrollerHeight || window.getComputedStyle(el).display === 'none' || el.offsetParent === null ) { return; } const { offset, direction } = this; function isReachEdge() { if (el === scroller) { const scrollTop = getScrollTop(el); if (direction === 'up') { return scrollTop <= offset; } const targetBottom = scrollTop + scrollerHeight; return scroller.scrollHeight - targetBottom <= offset; } if (direction === 'up') { return getScrollTop(scroller) - getElementTop(el) <= offset; } const elBottom = getElementTop(el) + getVisibleHeight(el) - getElementTop(scroller); return elBottom - scrollerHeight <= offset; } if (isReachEdge()) { this.$emit('input', true); this.$emit('load'); } }, clickErrorText() { this.$emit('update:error', false); this.$nextTick(this.check); }, handler(bind) { /* istanbul ignore else */ if (this.binded !== bind) { this.binded = bind; (bind ? on : off)(this.scroller, 'scroll', this.check); } } }, render(h) { return (
{this.direction === 'down' && this.slots()} {this.loading && (
{this.slots('loading') || [ , {this.loadingText || t('loading')} ]}
)} {this.finished && this.finishedText && (
{this.finishedText}
)} {this.error && this.errorText && (
{this.errorText}
)} {this.direction === 'up' && this.slots()}
); } });