tdesign-vue
Version:
259 lines (255 loc) • 9.49 kB
JavaScript
/**
* tdesign v1.14.1
* (c) 2025 tdesign
* @license MIT
*/
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import { reactive, computed, ref, nextTick, watch, onMounted, toRefs } from '@vue/composition-api';
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var useVirtualScroll = function useVirtualScroll(_ref) {
var data = _ref.data,
container = _ref.container,
_ref$fixedHeight = _ref.fixedHeight,
fixedHeight = _ref$fixedHeight === void 0 ? false : _ref$fixedHeight,
_ref$lineHeight = _ref.lineHeight,
lineHeight = _ref$lineHeight === void 0 ? 30 : _ref$lineHeight,
_ref$bufferSize = _ref.bufferSize,
bufferSize = _ref$bufferSize === void 0 ? 20 : _ref$bufferSize,
_ref$threshold = _ref.threshold,
threshold = _ref$threshold === void 0 ? 100 : _ref$threshold;
var state = reactive({
visibleData: [],
cachedHeight: [],
cachedScrollY: []
});
var isVirtual = computed(function () {
return data.value.length > threshold;
});
var updateId = ref(0);
var trs = /* @__PURE__ */new Map();
var visibleCount = 0;
var beforeScrollTop = 0;
var index = 0;
var offset = 0;
var start = 0;
var last = 0;
var reset = function reset() {
data.value.forEach(function (item, i) {
item.$index = i;
if (fixedHeight) {
state.cachedScrollY[i] = i * lineHeight;
}
});
if (!fixedHeight) {
state.cachedScrollY[data.value.length - 1] = void 0;
}
};
reset();
var scrollHeight = computed(function () {
var cachedHeight = state.cachedHeight;
var length = cachedHeight.length;
if (length) {
var maxScrollY = cachedHeight.reduce(function (sum, v) {
return sum + v || lineHeight;
}, 0);
if (cachedHeight.length === data.value.length) {
return maxScrollY;
}
var average = maxScrollY / cachedHeight.length;
return maxScrollY + (data.value.length - cachedHeight.length) * average;
}
return isVirtual.value ? data.value.length * lineHeight : 0;
});
var translateY = computed(function () {
var visibleData = state.visibleData;
var firstRow = visibleData[0];
if (firstRow) {
var _state$cachedScrollY$;
return visibleData.length === 1 ? 0 : (_state$cachedScrollY$ = state.cachedScrollY[firstRow.$index]) !== null && _state$cachedScrollY$ !== void 0 ? _state$cachedScrollY$ : 0;
}
return 0;
});
var updateVisibleData = function updateVisibleData() {
last = Math.min(start + visibleCount + bufferSize * 2, data.value.length);
state.visibleData = data.value.slice(start, last);
};
var calculateScrollY = function calculateScrollY() {
var _anchorDom$getBoundin;
var anchorDom = trs.get(index);
if (!anchorDom) {
return;
}
var anchorDomHeight = anchorDom === null || anchorDom === void 0 || (_anchorDom$getBoundin = anchorDom.getBoundingClientRect()) === null || _anchorDom$getBoundin === void 0 ? void 0 : _anchorDom$getBoundin.height;
state.cachedScrollY[index] = container.value.scrollTop - offset;
state.cachedHeight[index] = anchorDomHeight;
for (var i = index + 1; i <= state.visibleData[state.visibleData.length - 1].$index; i++) {
var tr = trs.get(i);
var _ref2 = (tr === null || tr === void 0 ? void 0 : tr.getBoundingClientRect()) || {},
height = _ref2.height;
state.cachedHeight[i] = height;
var scrollY = state.cachedScrollY[i - 1] + state.cachedHeight[i - 1];
state.cachedScrollY.splice(i, 1, scrollY);
}
for (var _i = index - 1; _i >= state.visibleData[0].$index; _i--) {
var _tr = trs.get(_i);
var _ref3 = (_tr === null || _tr === void 0 ? void 0 : _tr.getBoundingClientRect()) || {},
_height = _ref3.height;
state.cachedHeight[_i] = _height;
var _scrollY = state.cachedScrollY[_i + 1] - state.cachedHeight[_i];
state.cachedScrollY.splice(_i, 1, _scrollY);
}
if (state.cachedScrollY[0] > 0) {
var distance = state.cachedScrollY[0];
var length = Math.min(last, data.value.length);
for (var _i2 = 0; _i2 < length; _i2++) {
state.cachedScrollY.splice(_i2, 1, state.cachedScrollY[_i2] - distance);
}
var scrollTop = state.cachedScrollY[index - 1] ? state.cachedScrollY[index - 1] + offset : offset;
container.value.scrollTop = scrollTop;
beforeScrollTop = scrollTop;
}
if (state.cachedScrollY[start] < 0) {
var s = state.cachedHeight.slice(0, Math.max(0, index)).reduce(function (sum, v) {
return sum + v;
}, 0) + offset;
container.value.scrollTop = s;
beforeScrollTop = s;
if (s === 0) {
index = 0;
offset = 0;
}
}
nextTick(function () {
var _container$value = container.value,
scrollTop = _container$value.scrollTop,
scrollHeight2 = _container$value.scrollHeight,
clientHeight = _container$value.clientHeight;
if (scrollTop + clientHeight === scrollHeight2) {
for (var _i3 = last - 1; _i3 >= start; _i3--) {
if (_i3 === last - 1) {
state.cachedScrollY.splice(_i3, 1, scrollHeight2.value - state.cachedHeight[_i3]);
} else {
state.cachedScrollY.splice(_i3, 1, state.cachedScrollY[_i3 + 1] - state.cachedHeight[_i3]);
}
}
}
});
};
var handleScroll = function handleScroll() {
if (!isVirtual.value) return;
if (!container.value) return;
var scrollTop = container.value.scrollTop;
var distance = scrollTop - beforeScrollTop;
beforeScrollTop = scrollTop;
distance += offset;
var lastIndex = index;
if (!distance) return;
if (distance >= 0) {
while (lastIndex < data.value.length && distance > (state.cachedHeight[lastIndex] || lineHeight)) {
if (!state.cachedHeight[lastIndex]) {
state.cachedHeight[lastIndex] = lineHeight;
}
distance -= state.cachedHeight[lastIndex];
lastIndex += 1;
}
if (lastIndex >= data.value.length) {
index = data.value.length - 1;
offset = 0;
} else {
index = lastIndex;
offset = distance;
}
var _container$value2 = container.value,
clientHeight = _container$value2.clientHeight,
scrollHeight2 = _container$value2.scrollHeight;
if (scrollTop + clientHeight === scrollHeight2) {
index = data.value.length - visibleCount + 1;
}
if (start <= index - bufferSize) {
start = Math.min(data.value.length - visibleCount, index - bufferSize);
if (start < 0) {
start = 0;
}
}
} else {
while (distance < 0) {
lastIndex -= 1;
if (!state.cachedHeight[lastIndex]) {
state.cachedHeight[lastIndex] = lineHeight;
}
distance += state.cachedHeight[lastIndex];
}
if (lastIndex < 0) {
index = 0;
offset = 0;
} else {
index = lastIndex;
offset = distance;
}
calculateScrollY();
if (start > index - bufferSize) {
start = Math.max(0, index - bufferSize);
}
}
updateVisibleData();
};
!fixedHeight && watch(updateId, calculateScrollY, {
flush: "post"
});
var handleRowMounted = function handleRowMounted() {
if (!isVirtual.value) return;
updateId.value += 1;
};
watch(data, function () {
reset();
state.visibleData = [];
state.cachedScrollY = [];
state.cachedHeight = [];
beforeScrollTop = 0;
index = 0;
offset = 0;
start = 0;
trs.clear();
if (data.value.length <= threshold) {
state.visibleData = data.value;
} else {
updateVisibleData();
}
container.value && (container.value.scrollTop = 0);
});
var mounted = false;
var refreshContainer = function refreshContainer() {
if (mounted) {
visibleCount = Math.ceil(container.value.offsetHeight / lineHeight);
updateVisibleData();
}
};
onMounted(function () {
if (!window || !window.IntersectionObserver) {
return;
}
var ob = new window.IntersectionObserver(function (entries) {
var entry = entries[0];
if (entry.isIntersecting || entry.intersectionRatio) {
mounted = true;
isVirtual.value && refreshContainer();
ob.unobserve(container.value);
}
});
container.value && ob.observe(container.value);
});
return _objectSpread(_objectSpread({
trs: trs,
scrollHeight: scrollHeight
}, toRefs(state)), {}, {
translateY: translateY,
handleScroll: handleScroll,
handleRowMounted: handleRowMounted,
refreshContainer: refreshContainer,
fixedHeight: fixedHeight,
calculateScrollY: calculateScrollY
});
};
export { useVirtualScroll as default };
//# sourceMappingURL=useVirtualScroll.js.map