| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- "use strict";
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.default = useScrollTo;
- var _raf = _interopRequireDefault(require("../../_util/raf"));
- function useScrollTo(containerRef, mergedData, heights, props, getKey, collectHeight, syncScrollTop, triggerFlash) {
- let scroll;
- return arg => {
- // When not argument provided, we think dev may want to show the scrollbar
- if (arg === null || arg === undefined) {
- triggerFlash();
- return;
- }
- // Normal scroll logic
- _raf.default.cancel(scroll);
- const data = mergedData.value;
- const itemHeight = props.itemHeight;
- if (typeof arg === 'number') {
- syncScrollTop(arg);
- } else if (arg && typeof arg === 'object') {
- let index;
- const {
- align
- } = arg;
- if ('index' in arg) {
- ({
- index
- } = arg);
- } else {
- index = data.findIndex(item => getKey(item) === arg.key);
- }
- const {
- offset = 0
- } = arg;
- // We will retry 3 times in case dynamic height shaking
- const syncScroll = (times, targetAlign) => {
- if (times < 0 || !containerRef.value) return;
- const height = containerRef.value.clientHeight;
- let needCollectHeight = false;
- let newTargetAlign = targetAlign;
- // Go to next frame if height not exist
- if (height) {
- const mergedAlign = targetAlign || align;
- // Get top & bottom
- let stackTop = 0;
- let itemTop = 0;
- let itemBottom = 0;
- const maxLen = Math.min(data.length, index);
- for (let i = 0; i <= maxLen; i += 1) {
- const key = getKey(data[i]);
- itemTop = stackTop;
- const cacheHeight = heights.get(key);
- itemBottom = itemTop + (cacheHeight === undefined ? itemHeight : cacheHeight);
- stackTop = itemBottom;
- if (i === index && cacheHeight === undefined) {
- needCollectHeight = true;
- }
- }
- const scrollTop = containerRef.value.scrollTop;
- // Scroll to
- let targetTop = null;
- switch (mergedAlign) {
- case 'top':
- targetTop = itemTop - offset;
- break;
- case 'bottom':
- targetTop = itemBottom - height + offset;
- break;
- default:
- {
- const scrollBottom = scrollTop + height;
- if (itemTop < scrollTop) {
- newTargetAlign = 'top';
- } else if (itemBottom > scrollBottom) {
- newTargetAlign = 'bottom';
- }
- }
- }
- if (targetTop !== null && targetTop !== scrollTop) {
- syncScrollTop(targetTop);
- }
- }
- // We will retry since element may not sync height as it described
- scroll = (0, _raf.default)(() => {
- if (needCollectHeight) {
- collectHeight();
- }
- syncScroll(times - 1, newTargetAlign);
- }, 2);
- };
- syncScroll(5);
- }
- };
- }
|