// Utils import { createNamespace } from '../utils'; import { isHidden } from '../utils/dom/style'; import { getScroller } from '../utils/dom/scroll'; // Mixins import { BindEventMixin } from '../mixins/bind-event'; // Components import Loading from '../loading'; var _createNamespace = createNamespace('list'), createComponent = _createNamespace[0], bem = _createNamespace[1], t = _createNamespace[2]; export default createComponent({ mixins: [BindEventMixin(function (bind) { if (!this.scroller) { this.scroller = getScroller(this.$el); } bind(this.scroller, 'scroll', this.check); })], model: { prop: 'loading' }, props: { error: Boolean, loading: Boolean, finished: Boolean, errorText: String, loadingText: String, finishedText: String, immediateCheck: { type: Boolean, default: true }, offset: { type: [Number, String], default: 300 }, direction: { type: String, default: 'down' } }, data: function data() { return { // use sync innerLoading state to avoid repeated loading in some edge cases innerLoading: this.loading }; }, updated: function updated() { this.innerLoading = this.loading; }, mounted: function mounted() { if (this.immediateCheck) { this.check(); } }, watch: { loading: 'check', finished: 'check' }, methods: { // @exposed-api check: function check() { var _this = this; this.$nextTick(function () { if (_this.innerLoading || _this.finished || _this.error) { return; } var el = _this.$el, scroller = _this.scroller, offset = _this.offset, direction = _this.direction; var scrollerRect; if (scroller.getBoundingClientRect) { scrollerRect = scroller.getBoundingClientRect(); } else { scrollerRect = { top: 0, bottom: scroller.innerHeight }; } var scrollerHeight = scrollerRect.bottom - scrollerRect.top; /* istanbul ignore next */ if (!scrollerHeight || isHidden(el)) { return false; } var isReachEdge = false; var placeholderRect = _this.$refs.placeholder.getBoundingClientRect(); if (direction === 'up') { isReachEdge = scrollerRect.top - placeholderRect.top <= offset; } else { isReachEdge = placeholderRect.bottom - scrollerRect.bottom <= offset; } if (isReachEdge) { _this.innerLoading = true; _this.$emit('input', true); _this.$emit('load'); } }); }, clickErrorText: function clickErrorText() { this.$emit('update:error', false); this.check(); }, genLoading: function genLoading() { var h = this.$createElement; if (this.innerLoading && !this.finished) { return h("div", { "key": "loading", "class": bem('loading') }, [this.slots('loading') || h(Loading, { "attrs": { "size": "16" } }, [this.loadingText || t('loading')])]); } }, genFinishedText: function genFinishedText() { var h = this.$createElement; if (this.finished) { var text = this.slots('finished') || this.finishedText; if (text) { return h("div", { "class": bem('finished-text') }, [text]); } } }, genErrorText: function genErrorText() { var h = this.$createElement; if (this.error) { var text = this.slots('error') || this.errorText; if (text) { return h("div", { "on": { "click": this.clickErrorText }, "class": bem('error-text') }, [text]); } } } }, render: function render() { var h = arguments[0]; var Placeholder = h("div", { "ref": "placeholder", "key": "placeholder", "class": bem('placeholder') }); return h("div", { "class": bem(), "attrs": { "role": "feed", "aria-busy": this.innerLoading } }, [this.direction === 'down' ? this.slots() : Placeholder, this.genLoading(), this.genFinishedText(), this.genErrorText(), this.direction === 'up' ? this.slots() : Placeholder]); } });