bee-tree/build/infiniteScroll.js

325 lines
12 KiB
JavaScript
Raw Normal View History

2019-08-14 20:50:48 +08:00
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _util = require('./util');
var _config = require('./config');
var _config2 = _interopRequireDefault(_config);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
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) : _defaults(subClass, superClass); } /**
* 处理滚动加载逻辑
*/
var InfiniteScroll = function (_Component) {
_inherits(InfiniteScroll, _Component);
function InfiniteScroll(props) {
_classCallCheck(this, InfiniteScroll);
//默认显示20条rowsInView根据定高算的。在非固定高下这个只是一个大概的值。
var _this = _possibleConstructorReturn(this, _Component.call(this, props));
_this.eventListenerOptions = function () {
var options = _this.props.useCapture;
if (_this.isPassiveSupported()) {
options = {
useCapture: _this.props.useCapture,
passive: true
};
}
return options;
};
_this.mousewheelListener = function (e) {
// Prevents Chrome hangups
// See: https://stackoverflow.com/questions/47524205/random-high-content-download-time-in-chrome/47684257#47684257
if (e.deltaY === 1 && !_this.isPassiveSupported()) {
e.preventDefault();
}
};
_this.scrollListener = function () {
var el = _this.scrollComponent;
var parentNode = _this.getParentElement(el);
_this.scrollTop = parentNode.scrollTop;
_this.handleScrollY();
2019-08-14 20:50:48 +08:00
};
_this.handleScrollY = function () {
var store = _this.props.store;
var parentElement = _this.getParentElement(_this.scrollComponent);
if (!parentElement) {
return;
}
var scrollEl = parentElement;
var scrollY = scrollEl && scrollEl.clientHeight;
var rowHeight = store.getState().rowHeight;
2019-09-19 16:01:41 +08:00
//默认显示20条rowsInView根据定高算的。在非固定高下这个只是一个大概的值。
_this.rowsInView = scrollY ? Math.floor(scrollY / rowHeight) : _config2["default"].defaultRowsInView;
2019-08-14 20:50:48 +08:00
var currentIndex = _this.currentIndex,
startIndex = _this.startIndex,
endIndex = _this.endIndex,
treeList = _this.treeList,
loadCount = _this.loadCount,
rowsInView = _this.rowsInView;
var index = 0;
var tempScrollTop = _this.scrollTop;
//根据 scrollTop 计算 currentIndex
while (tempScrollTop > 0) {
2019-09-19 16:01:41 +08:00
tempScrollTop -= rowHeight;
2019-08-14 20:50:48 +08:00
if (tempScrollTop > 0) {
index += 1;
}
}
//true 为向下滚动, false 为向上滚动
var isScrollDown = index - currentIndex > 0 ? true : false;
if (index < 0) index = 0;
//如果之前的索引和下一次的不一样则重置索引和滚动的位置
_this.currentIndex = currentIndex !== index ? index : currentIndex;
// 如果rowsInView 小于 缓存的数据则重新render
// 向下滚动 下临界值超出缓存的endIndex则重新渲染
if (isScrollDown && rowsInView + index > endIndex - _config2["default"].rowDiff) {
startIndex = index - _config2["default"].loadBuffer > 0 ? index - _config2["default"].loadBuffer : 0;
endIndex = startIndex + loadCount;
if (endIndex > treeList.length) {
endIndex = treeList.length;
}
if (endIndex > _this.endIndex) {
_this.startIndex = startIndex;
_this.endIndex = endIndex;
_this.sliceTreeList(_this.startIndex, _this.endIndex);
}
}
// 向上滚动当前的index是否已经加载currentIndex若干上临界值小于startIndex则重新渲染
if (!isScrollDown && index < startIndex + _config2["default"].rowDiff) {
startIndex = index - _config2["default"].loadBuffer;
if (startIndex < 0) {
startIndex = 0;
}
if (startIndex <= _this.startIndex) {
_this.startIndex = startIndex;
_this.endIndex = _this.startIndex + loadCount;
_this.sliceTreeList(_this.startIndex, _this.endIndex);
}
}
};
_this.sliceTreeList = function (startIndex, endIndex) {
2019-08-26 21:13:42 +08:00
var newTreeList = []; //存储截取后的新数据
newTreeList = _this.treeList.slice(startIndex, endIndex);
2019-08-14 20:50:48 +08:00
_this.props.handleTreeListChange && _this.props.handleTreeListChange(newTreeList, startIndex, endIndex);
};
_this.rowsInView = _config2["default"].defaultRowsInView;
//一维数组
_this.treeList = props.treeList;
//一次加载多少数据
_this.loadCount = _config2["default"].loadBuffer ? _this.rowsInView + _config2["default"].loadBuffer * 2 : 16;
//可视区第一条数据的 index
_this.currentIndex = 0;
_this.startIndex = _this.currentIndex; //数据开始位置
_this.endIndex = _this.currentIndex + _this.loadCount; //数据结束位置
return _this;
}
InfiniteScroll.prototype.componentDidMount = function componentDidMount() {
this.options = this.eventListenerOptions();
this.attachScrollListener();
};
InfiniteScroll.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
var newTreeList = nextProps.treeList;
var oldTreeList = this.props.treeList;
if (newTreeList !== oldTreeList) {
this.treeList = newTreeList;
this.handleScrollY();
}
};
// componentDidUpdate() {
// const el = this.scrollComponent;
// const parentNode = this.getParentElement(el);
// parentNode.scrollTop = this.scrollTop;
// };
2019-08-14 20:50:48 +08:00
InfiniteScroll.prototype.componentWillUnmount = function componentWillUnmount() {
this.detachScrollListener();
this.detachMousewheelListener();
};
InfiniteScroll.prototype.isPassiveSupported = function isPassiveSupported() {
var passive = false;
var testOptions = {
get passive() {
passive = true;
}
};
try {
document.addEventListener('test', null, testOptions);
document.removeEventListener('test', null, testOptions);
} catch (e) {
// ignore
}
return passive;
};
/**
* 解除mousewheel事件监听
*/
InfiniteScroll.prototype.detachMousewheelListener = function detachMousewheelListener() {
var scrollEl = window;
if (this.props.useWindow === false) {
scrollEl = this.scrollComponent.parentNode;
}
scrollEl.removeEventListener('mousewheel', this.mousewheelListener, this.options ? this.options : this.props.useCapture);
};
/**
* 解除scroll事件监听
*/
InfiniteScroll.prototype.detachScrollListener = function detachScrollListener() {
var scrollEl = window;
if (this.props.useWindow === false) {
scrollEl = this.getParentElement(this.scrollComponent);
}
scrollEl.removeEventListener('scroll', this.scrollListener, this.options ? this.options : this.props.useCapture);
scrollEl.removeEventListener('resize', this.scrollListener, this.options ? this.options : this.props.useCapture);
};
/**
* 获取父组件(用户自定义父组件或者当前dom的parentNode)
* @param {*} el
*/
InfiniteScroll.prototype.getParentElement = function getParentElement(el) {
var scrollParent = this.props.getScrollParent && this.props.getScrollParent();
if (scrollParent != null) {
return scrollParent;
}
return el && el.parentNode;
};
InfiniteScroll.prototype.filterProps = function filterProps(props) {
return props;
};
/**
* 绑定scroll事件
*/
InfiniteScroll.prototype.attachScrollListener = function attachScrollListener() {
2019-09-19 16:01:41 +08:00
var store = this.props.store;
2019-08-14 20:50:48 +08:00
2019-09-19 16:01:41 +08:00
var parentElement = this.getParentElement(this.scrollComponent);
2019-08-14 20:50:48 +08:00
if (!parentElement) {
return;
}
var scrollEl = parentElement;
var scrollY = scrollEl && scrollEl.clientHeight;
2019-09-19 16:01:41 +08:00
var rowHeight = store.getState().rowHeight;
//默认显示20条rowsInView根据定高算的。
2019-09-19 16:01:41 +08:00
this.rowsInView = scrollY ? Math.floor(scrollY / rowHeight) : _config2["default"].defaultRowsInView;
2019-08-14 20:50:48 +08:00
scrollEl.addEventListener('scroll', (0, _util.throttle)(this.scrollListener, 150), this.options ? this.options : this.props.useCapture);
scrollEl.addEventListener('resize', (0, _util.throttle)(this.scrollListener, 150), this.options ? this.options : this.props.useCapture);
2019-08-14 20:50:48 +08:00
};
/**
* 滚动事件监听
*/
/**
* @description 根据返回的scrollTop计算当前的索引
*/
/**
* 根据 startIndex endIndex 截取数据
* @param startIndex
* @param endIndex
*/
InfiniteScroll.prototype.render = function render() {
var _this2 = this;
var _props = this.props,
children = _props.children,
element = _props.element,
ref = _props.ref,
getScrollParent = _props.getScrollParent,
treeList = _props.treeList,
handleTreeListChange = _props.handleTreeListChange,
store = _props.store,
props = _objectWithoutProperties(_props, ['children', 'element', 'ref', 'getScrollParent', 'treeList', 'handleTreeListChange', 'store']);
2019-08-14 20:50:48 +08:00
props.ref = function (node) {
_this2.scrollComponent = node;
if (ref) {
ref(node);
}
};
var childrenArray = [children];
return _react2["default"].createElement(element, props, childrenArray);
};
return InfiniteScroll;
}(_react.Component);
InfiniteScroll.propTypes = {
children: _propTypes2["default"].node.isRequired,
element: _propTypes2["default"].node,
ref: _propTypes2["default"].func,
getScrollParent: _propTypes2["default"].func,
treeList: _propTypes2["default"].array,
handleTreeListChange: _propTypes2["default"].func
};
InfiniteScroll.defaultProps = {
element: 'div',
ref: null,
getScrollParent: null,
treeList: [],
handleTreeListChange: function handleTreeListChange() {}
};
exports["default"] = InfiniteScroll;
module.exports = exports['default'];