@nutui/nutui-react-taro
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
185 lines (184 loc) • 7.37 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "VirtualList", {
enumerable: true,
get: function() {
return VirtualList;
}
});
var _interop_require_default = require("@swc/helpers/_/_interop_require_default");
var _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
var _object_spread = require("@swc/helpers/_/_object_spread");
var _object_spread_props = require("@swc/helpers/_/_object_spread_props");
var _object_without_properties = require("@swc/helpers/_/_object_without_properties");
var _sliced_to_array = require("@swc/helpers/_/_sliced_to_array");
var _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
var _components = require("@tarojs/components");
var _classnames = /*#__PURE__*/ _interop_require_default._(require("classnames"));
var _getsysteminfo = require("../../utils/taro/get-system-info");
var _utils = require("./utils");
var _typings = require("../../utils/typings");
var defaultProps = (0, _object_spread_props._)((0, _object_spread._)({}, _typings.ComponentDefaults), {
list: [],
itemHeight: 66,
margin: 10,
itemEqual: true,
overscan: 2
});
var VirtualList = function VirtualList(props) {
var _ref = (0, _object_spread._)({}, defaultProps, props), list = _ref.list, itemRender = _ref.itemRender, itemHeight = _ref.itemHeight, margin = _ref.margin, itemEqual = _ref.itemEqual, overscan = _ref.overscan, key = _ref.key, onScroll = _ref.onScroll, className = _ref.className, origContainerHeight = _ref.containerHeight, rest = (0, _object_without_properties._)(_ref, [
"list",
"itemRender",
"itemHeight",
"margin",
"itemEqual",
"overscan",
"key",
"onScroll",
"className",
"containerHeight"
]);
var clientHeight = (0, _react.useMemo)(function() {
return (0, _getsysteminfo.getWindowInfo)().windowHeight - 5 || 667;
}, []);
var containerHeight = (0, _react.useMemo)(function() {
return origContainerHeight !== null && origContainerHeight !== void 0 ? origContainerHeight : clientHeight;
}, [
origContainerHeight,
clientHeight
]);
var _useState = (0, _sliced_to_array._)((0, _react.useState)(0), 2), startOffset = _useState[0], setStartOffset = _useState[1];
var start = (0, _react.useRef)(0);
// 虚拟列表容器ref
var scrollRef = (0, _react.useRef)(null);
// 虚拟列表显示区域ref
var itemsRef = (0, _react.useRef)(null);
// 列表位置信息
var _useState1 = (0, _sliced_to_array._)((0, _react.useState)([
{
index: 0,
left: 0,
top: 0,
bottom: 0,
width: 0,
height: 0,
right: 0
}
]), 2), positions = _useState1[0], setPositions = _useState1[1];
var _useState2 = (0, _sliced_to_array._)((0, _react.useState)(containerHeight || 0), 2), offSetSize = _useState2[0], setOffSetSize = _useState2[1];
// 初始计算可视区域展示数量
(0, _react.useEffect)(function() {
setPositions(function(options) {
return (0, _object_spread_props._)((0, _object_spread._)({}, options), {
endIndex: visibleCount()
});
});
}, [
itemHeight,
overscan,
offSetSize
]);
(0, _react.useEffect)(function() {
if (containerHeight) return;
setOffSetSize(getContainerHeight());
}, [
containerHeight
]);
(0, _react.useEffect)(function() {
var pos = (0, _utils.initPositinoCache)(itemHeight + margin, list.length);
setPositions(pos);
}, [
itemHeight,
list
]);
// 可视区域总高度
var getContainerHeight = function getContainerHeight() {
// 初始首页列表高度
var initH = (itemHeight + margin) * list.length;
// 未设置containerHeight高度,判断首页高度小于设备高度时,滚动容器高度为首页数据高度,减5为分页触发的偏移量
return initH < clientHeight ? initH + overscan * (itemHeight + margin) - 5 : Math.min(containerHeight, clientHeight) // Math.min(containerHeight, clientHeight)
;
};
// 可视区域条数
var visibleCount = function visibleCount() {
return Math.ceil(getContainerHeight() / (itemHeight + margin)) + overscan;
};
var end = function end() {
return start.current + visibleCount();
};
var listHeight = function listHeight() {
return list.length * (itemHeight + margin);
};
var visibleData = function visibleData() {
return list.slice(start.current, Math.min(end(), list.length));
};
var updateTotalSize = (0, _react.useCallback)(function() {
if (!itemsRef.current) return;
var items = itemsRef.current.children;
if (!items.length) return;
// 更新缓存
(0, _utils.updateItemSize)(positions, items, 'height', margin);
}, [
positions
]);
// 滚动监听
var listScroll = function listScroll(e) {
var scrollTop = e.target.scrollTop;
if (scrollTop <= 0) {
e.target.scrollTop = 0;
return setStartOffset(0);
}
if (!itemEqual) {
updateTotalSize();
}
start.current = Math.floor(scrollTop / (itemHeight + margin));
setStartOffset(scrollTop - scrollTop % (itemHeight + margin));
var endIndex = end();
// list 变动说明触底
if (endIndex > list.length - 1) {
onScroll && onScroll();
}
};
return /*#__PURE__*/ _react.default.createElement(_components.View, (0, _object_spread_props._)((0, _object_spread._)({
className: (0, _classnames.default)('nut-virtualList-box', className)
}, rest), {
style: {
height: containerHeight ? "".concat(offSetSize, "px") : ''
}
}), /*#__PURE__*/ _react.default.createElement(_components.ScrollView, {
scrollY: true,
bounces: false,
type: "list",
ref: scrollRef,
className: "nut-virtuallist",
style: {
height: "".concat(getContainerHeight(), "px")
},
onScroll: listScroll
}, /*#__PURE__*/ _react.default.createElement(_components.View, {
className: "nut-virtuallist-phantom",
style: {
height: "".concat(listHeight(), "px")
}
}), /*#__PURE__*/ _react.default.createElement(_components.View, {
className: "nut-virtuallist-container",
ref: itemsRef,
style: {
transform: "translate3d(0, ".concat(startOffset, "px, 0)")
}
}, visibleData().map(function(data, index) {
var dataIndex = start.current + index;
var keyVal = key && data[key] ? data[key] : dataIndex;
return /*#__PURE__*/ _react.default.createElement(_components.View, {
"data-index": "".concat(dataIndex),
className: "nut-virtuallist-item",
key: "".concat(keyVal),
style: {
height: "".concat(itemEqual ? "".concat(itemHeight, "px") : 'auto')
}
}, itemRender ? itemRender(data, dataIndex, index) : data);
}))));
};
VirtualList.displayName = 'NutVirtualList';
;