index.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { use } from '../utils';
  2. import Loading from '../loading';
  3. import { on, off } from '../utils/event';
  4. import { getScrollTop, getElementTop, getVisibleHeight, getScrollEventTarget } from '../utils/scroll';
  5. var _use = use('list'),
  6. sfc = _use[0],
  7. bem = _use[1],
  8. t = _use[2];
  9. export default sfc({
  10. model: {
  11. prop: 'loading'
  12. },
  13. props: {
  14. error: Boolean,
  15. loading: Boolean,
  16. finished: Boolean,
  17. errorText: String,
  18. loadingText: String,
  19. finishedText: String,
  20. immediateCheck: {
  21. type: Boolean,
  22. "default": true
  23. },
  24. offset: {
  25. type: Number,
  26. "default": 300
  27. },
  28. direction: {
  29. type: String,
  30. "default": 'down'
  31. }
  32. },
  33. mounted: function mounted() {
  34. this.scroller = getScrollEventTarget(this.$el);
  35. this.handler(true);
  36. if (this.immediateCheck) {
  37. this.$nextTick(this.check);
  38. }
  39. },
  40. destroyed: function destroyed() {
  41. this.handler(false);
  42. },
  43. activated: function activated() {
  44. this.handler(true);
  45. },
  46. deactivated: function deactivated() {
  47. this.handler(false);
  48. },
  49. watch: {
  50. loading: function loading() {
  51. this.$nextTick(this.check);
  52. },
  53. finished: function finished() {
  54. this.$nextTick(this.check);
  55. }
  56. },
  57. methods: {
  58. check: function check() {
  59. if (this.loading || this.finished || this.error) {
  60. return;
  61. }
  62. var el = this.$el;
  63. var scroller = this.scroller;
  64. var scrollerHeight = getVisibleHeight(scroller);
  65. /* istanbul ignore next */
  66. if (!scrollerHeight || window.getComputedStyle(el).display === 'none' || el.offsetParent === null) {
  67. return;
  68. }
  69. var offset = this.offset,
  70. direction = this.direction;
  71. function isReachEdge() {
  72. if (el === scroller) {
  73. var scrollTop = getScrollTop(el);
  74. if (direction === 'up') {
  75. return scrollTop <= offset;
  76. }
  77. var targetBottom = scrollTop + scrollerHeight;
  78. return scroller.scrollHeight - targetBottom <= offset;
  79. }
  80. if (direction === 'up') {
  81. return getScrollTop(scroller) - getElementTop(el) <= offset;
  82. }
  83. var elBottom = getElementTop(el) + getVisibleHeight(el) - getElementTop(scroller);
  84. return elBottom - scrollerHeight <= offset;
  85. }
  86. if (isReachEdge()) {
  87. this.$emit('input', true);
  88. this.$emit('load');
  89. }
  90. },
  91. clickErrorText: function clickErrorText() {
  92. this.$emit('update:error', false);
  93. this.$nextTick(this.check);
  94. },
  95. handler: function handler(bind) {
  96. /* istanbul ignore else */
  97. if (this.binded !== bind) {
  98. this.binded = bind;
  99. (bind ? on : off)(this.scroller, 'scroll', this.check);
  100. }
  101. }
  102. },
  103. render: function render(h) {
  104. return h("div", {
  105. "class": bem()
  106. }, [this.direction === 'down' && this.slots(), this.loading && h("div", {
  107. "class": bem('loading'),
  108. "key": "loading"
  109. }, [this.slots('loading') || [h(Loading, {
  110. "class": bem('loading-icon')
  111. }), h("span", {
  112. "class": bem('loading-text')
  113. }, [this.loadingText || t('loading')])]]), this.finished && this.finishedText && h("div", {
  114. "class": bem('finished-text')
  115. }, [this.finishedText]), this.error && this.errorText && h("div", {
  116. "on": {
  117. "click": this.clickErrorText
  118. },
  119. "class": bem('error-text')
  120. }, [this.errorText]), this.direction === 'up' && this.slots()]);
  121. }
  122. });