UNPKG

ahooks-v2

Version:
196 lines (165 loc) 4.59 kB
"use strict"; var __read = this && this.__read || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) { ar.push(r.value); } } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __importDefault = this && this.__importDefault || function (mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var react_1 = require("react"); var useSize_1 = __importDefault(require("../useSize")); exports["default"] = function (list, options) { var containerRef = react_1.useRef(); var size = useSize_1["default"](containerRef); // 暂时禁止 cache // const distanceCache = useRef<{ [key: number]: number }>({}); var _a = __read(react_1.useState({ start: 0, end: 10 }), 2), state = _a[0], setState = _a[1]; var itemHeight = options.itemHeight, _b = options.overscan, overscan = _b === void 0 ? 5 : _b; if (!itemHeight) { console.warn('please enter a valid itemHeight'); } var getViewCapacity = function getViewCapacity(containerHeight) { if (typeof itemHeight === 'number') { return Math.ceil(containerHeight / itemHeight); } var _a = state.start, start = _a === void 0 ? 0 : _a; var sum = 0; var capacity = 0; for (var i = start; i < list.length; i++) { var height = itemHeight(i, list[i]); sum += height; if (sum >= containerHeight) { capacity = i; break; } } return capacity - start; }; var getOffset = function getOffset(scrollTop) { if (typeof itemHeight === 'number') { return Math.floor(scrollTop / itemHeight) + 1; } var sum = 0; var offset = 0; for (var i = 0; i < list.length; i++) { var height = itemHeight(i, list[i]); sum += height; if (sum >= scrollTop) { offset = i; break; } } return offset + 1; }; var calculateRange = function calculateRange() { var element = containerRef.current; if (element) { var offset = getOffset(element.scrollTop); var viewCapacity = getViewCapacity(element.clientHeight); var from = offset - overscan; var to = offset + viewCapacity + overscan; setState({ start: from < 0 ? 0 : from, end: to > list.length ? list.length : to }); } }; react_1.useEffect(function () { calculateRange(); }, [size.width, size.height, list.length]); var totalHeight = react_1.useMemo(function () { if (typeof itemHeight === 'number') { return list.length * itemHeight; } return list.reduce(function (sum, _, index) { return sum + itemHeight(index, list[index]); }, 0); }, [list.length]); var getDistanceTop = function getDistanceTop(index) { // 如果有缓存,优先返回缓存值 // if (enableCache && distanceCache.current[index]) { // return distanceCache.current[index]; // } if (typeof itemHeight === 'number') { var height_1 = index * itemHeight; // if (enableCache) { // distanceCache.current[index] = height; // } return height_1; } var height = list.slice(0, index).reduce(function (sum, _, i) { return sum + itemHeight(i, list[i]); }, 0); // if (enableCache) { // distanceCache.current[index] = height; // } return height; }; var scrollTo = function scrollTo(index) { if (containerRef.current) { containerRef.current.scrollTop = getDistanceTop(index); calculateRange(); } }; var offsetTop = react_1.useMemo(function () { return getDistanceTop(state.start); }, [state.start]); return { list: list.slice(state.start, state.end).map(function (ele, index) { return { data: ele, index: index + state.start }; }), scrollTo: scrollTo, containerProps: { ref: function ref(ele) { containerRef.current = ele; }, onScroll: function onScroll(e) { e.preventDefault(); calculateRange(); }, style: { overflowY: 'auto' } }, wrapperProps: { style: { width: '100%', height: totalHeight - offsetTop, marginTop: offsetTop } } }; };