mirror of
https://github.com/wu736139669/ASHEBShop-h5.git
synced 2026-10-08 19:36:33 +00:00
298 lines
11 KiB
JavaScript
298 lines
11 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
|
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
|
|
exports.isRangeVisible = isRangeVisible;
|
|
exports.scanForUnloadedRanges = scanForUnloadedRanges;
|
|
exports.forceUpdateReactVirtualizedComponent = forceUpdateReactVirtualizedComponent;
|
|
|
|
var _react = require('react');
|
|
|
|
var _propTypes = require('prop-types');
|
|
|
|
var _propTypes2 = _interopRequireDefault(_propTypes);
|
|
|
|
var _createCallbackMemoizer = require('../utils/createCallbackMemoizer');
|
|
|
|
var _createCallbackMemoizer2 = _interopRequireDefault(_createCallbackMemoizer);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
|
|
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
|
|
|
/**
|
|
* Higher-order component that manages lazy-loading for "infinite" data.
|
|
* This component decorates a virtual component and just-in-time prefetches rows as a user scrolls.
|
|
* It is intended as a convenience component; fork it if you'd like finer-grained control over data-loading.
|
|
*/
|
|
var InfiniteLoader = function (_PureComponent) {
|
|
_inherits(InfiniteLoader, _PureComponent);
|
|
|
|
function InfiniteLoader(props, context) {
|
|
_classCallCheck(this, InfiniteLoader);
|
|
|
|
var _this = _possibleConstructorReturn(this, (InfiniteLoader.__proto__ || Object.getPrototypeOf(InfiniteLoader)).call(this, props, context));
|
|
|
|
_this._loadMoreRowsMemoizer = (0, _createCallbackMemoizer2.default)();
|
|
|
|
_this._onRowsRendered = _this._onRowsRendered.bind(_this);
|
|
_this._registerChild = _this._registerChild.bind(_this);
|
|
return _this;
|
|
}
|
|
|
|
_createClass(InfiniteLoader, [{
|
|
key: 'resetLoadMoreRowsCache',
|
|
value: function resetLoadMoreRowsCache() {
|
|
this._loadMoreRowsMemoizer = (0, _createCallbackMemoizer2.default)();
|
|
}
|
|
}, {
|
|
key: 'render',
|
|
value: function render() {
|
|
var children = this.props.children;
|
|
|
|
|
|
return children({
|
|
onRowsRendered: this._onRowsRendered,
|
|
registerChild: this._registerChild
|
|
});
|
|
}
|
|
}, {
|
|
key: '_loadUnloadedRanges',
|
|
value: function _loadUnloadedRanges(unloadedRanges) {
|
|
var _this2 = this;
|
|
|
|
var loadMoreRows = this.props.loadMoreRows;
|
|
|
|
|
|
unloadedRanges.forEach(function (unloadedRange) {
|
|
var promise = loadMoreRows(unloadedRange);
|
|
if (promise) {
|
|
promise.then(function () {
|
|
// Refresh the visible rows if any of them have just been loaded.
|
|
// Otherwise they will remain in their unloaded visual state.
|
|
if (isRangeVisible({
|
|
lastRenderedStartIndex: _this2._lastRenderedStartIndex,
|
|
lastRenderedStopIndex: _this2._lastRenderedStopIndex,
|
|
startIndex: unloadedRange.startIndex,
|
|
stopIndex: unloadedRange.stopIndex
|
|
})) {
|
|
if (_this2._registeredChild) {
|
|
forceUpdateReactVirtualizedComponent(_this2._registeredChild, _this2._lastRenderedStartIndex);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}, {
|
|
key: '_onRowsRendered',
|
|
value: function _onRowsRendered(_ref) {
|
|
var _this3 = this;
|
|
|
|
var startIndex = _ref.startIndex,
|
|
stopIndex = _ref.stopIndex;
|
|
var _props = this.props,
|
|
isRowLoaded = _props.isRowLoaded,
|
|
minimumBatchSize = _props.minimumBatchSize,
|
|
rowCount = _props.rowCount,
|
|
threshold = _props.threshold;
|
|
|
|
|
|
this._lastRenderedStartIndex = startIndex;
|
|
this._lastRenderedStopIndex = stopIndex;
|
|
|
|
var unloadedRanges = scanForUnloadedRanges({
|
|
isRowLoaded: isRowLoaded,
|
|
minimumBatchSize: minimumBatchSize,
|
|
rowCount: rowCount,
|
|
startIndex: Math.max(0, startIndex - threshold),
|
|
stopIndex: Math.min(rowCount - 1, stopIndex + threshold)
|
|
});
|
|
|
|
// For memoize comparison
|
|
var squashedUnloadedRanges = unloadedRanges.reduce(function (reduced, unloadedRange) {
|
|
return reduced.concat([unloadedRange.startIndex, unloadedRange.stopIndex]);
|
|
}, []);
|
|
|
|
this._loadMoreRowsMemoizer({
|
|
callback: function callback() {
|
|
_this3._loadUnloadedRanges(unloadedRanges);
|
|
},
|
|
indices: { squashedUnloadedRanges: squashedUnloadedRanges }
|
|
});
|
|
}
|
|
}, {
|
|
key: '_registerChild',
|
|
value: function _registerChild(registeredChild) {
|
|
this._registeredChild = registeredChild;
|
|
}
|
|
}]);
|
|
|
|
return InfiniteLoader;
|
|
}(_react.PureComponent);
|
|
|
|
/**
|
|
* Determines if the specified start/stop range is visible based on the most recently rendered range.
|
|
*/
|
|
|
|
|
|
InfiniteLoader.defaultProps = {
|
|
minimumBatchSize: 10,
|
|
rowCount: 0,
|
|
threshold: 15
|
|
};
|
|
exports.default = InfiniteLoader;
|
|
process.env.NODE_ENV !== "production" ? InfiniteLoader.propTypes = {
|
|
/**
|
|
* Function responsible for rendering a virtualized component.
|
|
* This function should implement the following signature:
|
|
* ({ onRowsRendered, registerChild }) => PropTypes.element
|
|
*
|
|
* The specified :onRowsRendered function should be passed through to the child's :onRowsRendered property.
|
|
* The :registerChild callback should be set as the virtualized component's :ref.
|
|
*/
|
|
children: _propTypes2.default.func.isRequired,
|
|
|
|
/**
|
|
* Function responsible for tracking the loaded state of each row.
|
|
* It should implement the following signature: ({ index: number }): boolean
|
|
*/
|
|
isRowLoaded: _propTypes2.default.func.isRequired,
|
|
|
|
/**
|
|
* Callback to be invoked when more rows must be loaded.
|
|
* It should implement the following signature: ({ startIndex, stopIndex }): Promise
|
|
* The returned Promise should be resolved once row data has finished loading.
|
|
* It will be used to determine when to refresh the list with the newly-loaded data.
|
|
* This callback may be called multiple times in reaction to a single scroll event.
|
|
*/
|
|
loadMoreRows: _propTypes2.default.func.isRequired,
|
|
|
|
/**
|
|
* Minimum number of rows to be loaded at a time.
|
|
* This property can be used to batch requests to reduce HTTP requests.
|
|
*/
|
|
minimumBatchSize: _propTypes2.default.number.isRequired,
|
|
|
|
/**
|
|
* Number of rows in list; can be arbitrary high number if actual number is unknown.
|
|
*/
|
|
rowCount: _propTypes2.default.number.isRequired,
|
|
|
|
/**
|
|
* Threshold at which to pre-fetch data.
|
|
* A threshold X means that data will start loading when a user scrolls within X rows.
|
|
* This value defaults to 15.
|
|
*/
|
|
threshold: _propTypes2.default.number.isRequired
|
|
} : void 0;
|
|
function isRangeVisible(_ref2) {
|
|
var lastRenderedStartIndex = _ref2.lastRenderedStartIndex,
|
|
lastRenderedStopIndex = _ref2.lastRenderedStopIndex,
|
|
startIndex = _ref2.startIndex,
|
|
stopIndex = _ref2.stopIndex;
|
|
|
|
return !(startIndex > lastRenderedStopIndex || stopIndex < lastRenderedStartIndex);
|
|
}
|
|
|
|
/**
|
|
* Returns all of the ranges within a larger range that contain unloaded rows.
|
|
*/
|
|
function scanForUnloadedRanges(_ref3) {
|
|
var isRowLoaded = _ref3.isRowLoaded,
|
|
minimumBatchSize = _ref3.minimumBatchSize,
|
|
rowCount = _ref3.rowCount,
|
|
startIndex = _ref3.startIndex,
|
|
stopIndex = _ref3.stopIndex;
|
|
|
|
var unloadedRanges = [];
|
|
|
|
var rangeStartIndex = null;
|
|
var rangeStopIndex = null;
|
|
|
|
for (var index = startIndex; index <= stopIndex; index++) {
|
|
var loaded = isRowLoaded({ index: index });
|
|
|
|
if (!loaded) {
|
|
rangeStopIndex = index;
|
|
if (rangeStartIndex === null) {
|
|
rangeStartIndex = index;
|
|
}
|
|
} else if (rangeStopIndex !== null) {
|
|
unloadedRanges.push({
|
|
startIndex: rangeStartIndex,
|
|
stopIndex: rangeStopIndex
|
|
});
|
|
|
|
rangeStartIndex = rangeStopIndex = null;
|
|
}
|
|
}
|
|
|
|
// If :rangeStopIndex is not null it means we haven't ran out of unloaded rows.
|
|
// Scan forward to try filling our :minimumBatchSize.
|
|
if (rangeStopIndex !== null) {
|
|
var potentialStopIndex = Math.min(Math.max(rangeStopIndex, rangeStartIndex + minimumBatchSize - 1), rowCount - 1);
|
|
|
|
for (var _index = rangeStopIndex + 1; _index <= potentialStopIndex; _index++) {
|
|
if (!isRowLoaded({ index: _index })) {
|
|
rangeStopIndex = _index;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
unloadedRanges.push({
|
|
startIndex: rangeStartIndex,
|
|
stopIndex: rangeStopIndex
|
|
});
|
|
}
|
|
|
|
// Check to see if our first range ended prematurely.
|
|
// In this case we should scan backwards to try filling our :minimumBatchSize.
|
|
if (unloadedRanges.length) {
|
|
var firstUnloadedRange = unloadedRanges[0];
|
|
|
|
while (firstUnloadedRange.stopIndex - firstUnloadedRange.startIndex + 1 < minimumBatchSize && firstUnloadedRange.startIndex > 0) {
|
|
var _index2 = firstUnloadedRange.startIndex - 1;
|
|
|
|
if (!isRowLoaded({ index: _index2 })) {
|
|
firstUnloadedRange.startIndex = _index2;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return unloadedRanges;
|
|
}
|
|
|
|
/**
|
|
* Since RV components use shallowCompare we need to force a render (even though props haven't changed).
|
|
* However InfiniteLoader may wrap a Grid or it may wrap a Table or List.
|
|
* In the first case the built-in React forceUpdate() method is sufficient to force a re-render,
|
|
* But in the latter cases we need to use the RV-specific forceUpdateGrid() method.
|
|
* Else the inner Grid will not be re-rendered and visuals may be stale.
|
|
*
|
|
* Additionally, while a Grid is scrolling the cells can be cached,
|
|
* So it's important to invalidate that cache by recalculating sizes
|
|
* before forcing a rerender.
|
|
*/
|
|
function forceUpdateReactVirtualizedComponent(component) {
|
|
var currentIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
|
|
var recomputeSize = typeof component.recomputeGridSize === 'function' ? component.recomputeGridSize : component.recomputeRowHeights;
|
|
|
|
if (recomputeSize) {
|
|
recomputeSize.call(component, currentIndex);
|
|
} else {
|
|
component.forceUpdate();
|
|
}
|
|
} |