useScrollTo.js 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import _typeof from "@babel/runtime/helpers/esm/typeof";
  2. import raf from '../../_util/raf';
  3. export default function useScrollTo(containerRef, mergedData, heights, props, getKey, collectHeight, syncScrollTop, triggerFlash) {
  4. var scroll;
  5. return function (arg) {
  6. // When not argument provided, we think dev may want to show the scrollbar
  7. if (arg === null || arg === undefined) {
  8. triggerFlash();
  9. return;
  10. }
  11. // Normal scroll logic
  12. raf.cancel(scroll);
  13. var data = mergedData.value;
  14. var itemHeight = props.itemHeight;
  15. if (typeof arg === 'number') {
  16. syncScrollTop(arg);
  17. } else if (arg && _typeof(arg) === 'object') {
  18. var index;
  19. var align = arg.align;
  20. if ('index' in arg) {
  21. index = arg.index;
  22. } else {
  23. index = data.findIndex(function (item) {
  24. return getKey(item) === arg.key;
  25. });
  26. }
  27. var _arg$offset = arg.offset,
  28. offset = _arg$offset === void 0 ? 0 : _arg$offset;
  29. // We will retry 3 times in case dynamic height shaking
  30. var syncScroll = function syncScroll(times, targetAlign) {
  31. if (times < 0 || !containerRef.value) return;
  32. var height = containerRef.value.clientHeight;
  33. var needCollectHeight = false;
  34. var newTargetAlign = targetAlign;
  35. // Go to next frame if height not exist
  36. if (height) {
  37. var mergedAlign = targetAlign || align;
  38. // Get top & bottom
  39. var stackTop = 0;
  40. var itemTop = 0;
  41. var itemBottom = 0;
  42. var maxLen = Math.min(data.length, index);
  43. for (var i = 0; i <= maxLen; i += 1) {
  44. var key = getKey(data[i]);
  45. itemTop = stackTop;
  46. var cacheHeight = heights.get(key);
  47. itemBottom = itemTop + (cacheHeight === undefined ? itemHeight : cacheHeight);
  48. stackTop = itemBottom;
  49. if (i === index && cacheHeight === undefined) {
  50. needCollectHeight = true;
  51. }
  52. }
  53. var scrollTop = containerRef.value.scrollTop;
  54. // Scroll to
  55. var targetTop = null;
  56. switch (mergedAlign) {
  57. case 'top':
  58. targetTop = itemTop - offset;
  59. break;
  60. case 'bottom':
  61. targetTop = itemBottom - height + offset;
  62. break;
  63. default:
  64. {
  65. var scrollBottom = scrollTop + height;
  66. if (itemTop < scrollTop) {
  67. newTargetAlign = 'top';
  68. } else if (itemBottom > scrollBottom) {
  69. newTargetAlign = 'bottom';
  70. }
  71. }
  72. }
  73. if (targetTop !== null && targetTop !== scrollTop) {
  74. syncScrollTop(targetTop);
  75. }
  76. }
  77. // We will retry since element may not sync height as it described
  78. scroll = raf(function () {
  79. if (needCollectHeight) {
  80. collectHeight();
  81. }
  82. syncScroll(times - 1, newTargetAlign);
  83. }, 2);
  84. };
  85. syncScroll(5);
  86. }
  87. };
  88. }