feat:自动获取树节点真实行高

This commit is contained in:
yangchch6 2019-09-19 16:01:41 +08:00
parent 8534221dbd
commit bfcbb1225a
12 changed files with 231 additions and 41 deletions

View File

@ -34,6 +34,10 @@ var _config = require('./config');
var _config2 = _interopRequireDefault(_config);
var _createStore = require('./createStore');
var _createStore2 = _interopRequireDefault(_createStore);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": 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; }
@ -86,9 +90,26 @@ var Tree = function (_React$Component) {
_this.startIndex = 0;
_this.endIndex = _this.startIndex + _this.loadCount;
_this.cacheTreeNodes = []; //缓存 treenode 节点数组
_this.store = (0, _createStore2["default"])({ rowHeight: 24 }); //rowHeight 树节点的高度,此变量在滚动加载场景很关键
return _this;
}
/**
* lazyload 情况下需要获取树节点的真实高度
*/
Tree.prototype.componentDidMount = function componentDidMount() {
var lazyLoad = this.props.lazyLoad;
if (!lazyLoad) return;
var treenodes = this.tree.querySelectorAll('.u-tree-treenode-close')[0];
var rowHeight = treenodes.getBoundingClientRect().height;
this.store.setState({
rowHeight: rowHeight
});
};
Tree.prototype.componentWillMount = function componentWillMount() {
var _this2 = this;
@ -1074,7 +1095,8 @@ var Tree = function (_React$Component) {
className: 'u-tree-infinite-scroll',
treeList: flatTreeData,
handleTreeListChange: this.handleTreeListChange,
getScrollParent: getScrollContainer
getScrollParent: getScrollContainer,
store: this.store
},
_react2["default"].createElement(
'ul',
@ -1192,7 +1214,7 @@ var _initialiseProps = function _initialiseProps() {
}
var span = Math.abs(end - start);
if (span) {
sumHeight = span * _config2["default"].defaultHeight;
sumHeight = span * _this7.store.getState().rowHeight;
}
return sumHeight;
};

View File

@ -533,10 +533,11 @@ var TreeNode = function (_React$Component) {
};
var selectedCls = props.selected ? prefixCls + '-treenode-selected' : '';
var focusedCls = props.focused ? prefixCls + '-treenode-focused' : '';
var expandedCls = prefixCls + '-treenode-' + expandedState;
return _react2["default"].createElement(
'li',
_extends({}, liProps, { style: props.style,
className: (0, _classnames2["default"])(props.className, disabledCls, dragOverCls, filterCls, selectedCls, focusedCls)
className: (0, _classnames2["default"])(props.className, disabledCls, dragOverCls, filterCls, selectedCls, focusedCls, expandedCls)
}),
canRenderSwitcher ? this.renderSwitcher(props, expandedState) : noopSwitcher(),
props.checkable ? this.renderCheckbox(props) : null,

View File

@ -9,7 +9,6 @@ Object.defineProperty(exports, "__esModule", {
// 树懒加载功能,需要用到的变量
exports["default"] = {
defaultHeight: 24, //树节点行高
loadBuffer: 5, //懒加载时缓冲区数据量
defaultRowsInView: 20, //可视区数据量
rowDiff: 3 //行差值,需要重新截取数据的阈值

40
build/createStore.js Normal file
View File

@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
exports["default"] = createStore;
function createStore(initialState) {
var state = initialState;
var listeners = [];
function setState(partial) {
state = _extends({}, state, partial);
for (var i = 0; i < listeners.length; i++) {
listeners[i]();
}
}
function getState() {
return state;
}
function subscribe(listener) {
listeners.push(listener);
return function unsubscribe() {
var index = listeners.indexOf(listener);
listeners.splice(index, 1);
};
}
return {
setState: setState,
getState: getState,
subscribe: subscribe
};
}
module.exports = exports["default"];

View File

@ -72,6 +72,10 @@ var InfiniteScroll = function (_Component) {
};
_this.handleScrollY = function () {
var rowHeight = _this.props.store.getState().rowHeight;
//默认显示20条rowsInView根据定高算的。在非固定高下这个只是一个大概的值。
_this.rowsInView = scrollY ? Math.floor(scrollY / rowHeight) : _config2["default"].defaultRowsInView;
var currentIndex = _this.currentIndex,
startIndex = _this.startIndex,
endIndex = _this.endIndex,
@ -83,7 +87,7 @@ var InfiniteScroll = function (_Component) {
var tempScrollTop = _this.scrollTop;
//根据 scrollTop 计算 currentIndex
while (tempScrollTop > 0) {
tempScrollTop -= _config2["default"].defaultHeight;
tempScrollTop -= rowHeight;
if (tempScrollTop > 0) {
index += 1;
}
@ -233,17 +237,18 @@ var InfiniteScroll = function (_Component) {
InfiniteScroll.prototype.attachScrollListener = function attachScrollListener() {
var parentElement = this.getParentElement(this.scrollComponent);
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;
//默认显示20条rowsInView根据定高算的。在非固定高下这个只是一个大概的值。
this.rowsInView = scrollY ? Math.floor(scrollY / _config2["default"].defaultHeight) : _config2["default"].defaultRowsInView;
this.rowsInView = scrollY ? Math.floor(scrollY / rowHeight) : _config2["default"].defaultRowsInView;
scrollEl.addEventListener('scroll', this.scrollListener, this.options ? this.options : this.props.useCapture);
scrollEl.addEventListener('resize', this.scrollListener, this.options ? this.options : this.props.useCapture);

120
dist/demo.js vendored

File diff suppressed because one or more lines are too long

2
dist/demo.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -18,6 +18,7 @@ import {
import PropTypes from 'prop-types';
import { KeyCode } from 'tinper-bee-core';
import CONFIG from './config';
import createStore from './createStore';
function noop() {}
@ -49,6 +50,20 @@ class Tree extends React.Component {
this.startIndex = 0;
this.endIndex = this.startIndex + this.loadCount;
this.cacheTreeNodes = []; //缓存 treenode 节点数组
this.store = createStore({ rowHeight: 24 }); //rowHeight 树节点的高度,此变量在滚动加载场景很关键
}
/**
* lazyload 情况下需要获取树节点的真实高度
*/
componentDidMount() {
const { lazyLoad } = this.props;
if(!lazyLoad) return;
const treenodes = this.tree.querySelectorAll('.u-tree-treenode-close')[0];
let rowHeight = treenodes.getBoundingClientRect().height;
this.store.setState({
rowHeight: rowHeight
});
}
componentWillMount() {
@ -902,7 +917,7 @@ onExpand(treeNode,keyType) {
}
let span = Math.abs(end - start);
if(span) {
sumHeight = span * CONFIG.defaultHeight;
sumHeight = span * this.store.getState().rowHeight;
}
return sumHeight;
}
@ -1085,6 +1100,7 @@ onExpand(treeNode,keyType) {
treeList={flatTreeData}
handleTreeListChange={this.handleTreeListChange}
getScrollParent={getScrollContainer}
store={this.store}
>
<ul {...domProps} unselectable="true" ref={(el)=>{this.tree = el}} tabIndex={focusable && tabIndexValue}>
<li style={{height : preHeight}} className='u-treenode-start' key={'tree_node_start'}></li>

View File

@ -493,9 +493,10 @@ class TreeNode extends React.Component {
};
const selectedCls = props.selected?`${prefixCls}-treenode-selected`:'';
const focusedCls = props.focused ? `${prefixCls}-treenode-focused` : '';
const expandedCls = `${prefixCls}-treenode-${expandedState}`;
return (
<li {...liProps} style={props.style}
className={classNames(props.className, disabledCls, dragOverCls, filterCls,selectedCls,focusedCls) }
className={classNames(props.className, disabledCls, dragOverCls, filterCls,selectedCls,focusedCls,expandedCls) }
>
{canRenderSwitcher ? this.renderSwitcher(props, expandedState) : noopSwitcher()}
{props.checkable ? this.renderCheckbox(props) : null}

View File

@ -4,7 +4,6 @@
// 树懒加载功能,需要用到的变量
export default {
defaultHeight: 24, //树节点行高
loadBuffer: 5, //懒加载时缓冲区数据量
defaultRowsInView: 20, //可视区数据量
rowDiff: 3, //行差值,需要重新截取数据的阈值

31
src/createStore.js Normal file
View File

@ -0,0 +1,31 @@
export default function createStore(initialState) {
let state = initialState;
const listeners = [];
function setState(partial) {
state = { ...state, ...partial };
for (let i = 0; i < listeners.length; i++) {
listeners[i]();
}
}
function getState() {
return state;
}
function subscribe(listener) {
listeners.push(listener);
return function unsubscribe() {
const index = listeners.indexOf(listener);
listeners.splice(index, 1);
};
}
return {
setState,
getState,
subscribe,
};
}

View File

@ -143,17 +143,17 @@ export default class InfiniteScroll extends Component {
* 绑定scroll事件
*/
attachScrollListener() {
const { store } = this.props;
const parentElement = this.getParentElement(this.scrollComponent);
if (!parentElement) {
return;
}
let scrollEl = parentElement;
let scrollY = scrollEl && scrollEl.clientHeight;
let rowHeight = store.getState().rowHeight;
//默认显示20条rowsInView根据定高算的。在非固定高下这个只是一个大概的值。
this.rowsInView = scrollY ? Math.floor(scrollY / CONFIG.defaultHeight) : CONFIG.defaultRowsInView;
this.rowsInView = scrollY ? Math.floor(scrollY / rowHeight) : CONFIG.defaultRowsInView;
scrollEl.addEventListener(
'scroll',
@ -190,6 +190,10 @@ export default class InfiniteScroll extends Component {
* @description 根据返回的scrollTop计算当前的索引
*/
handleScrollY = () => {
let rowHeight = this.props.store.getState().rowHeight;
//默认显示20条rowsInView根据定高算的。在非固定高下这个只是一个大概的值。
this.rowsInView = scrollY ? Math.floor(scrollY / rowHeight) : CONFIG.defaultRowsInView;
let currentIndex = this.currentIndex,
startIndex = this.startIndex,
endIndex = this.endIndex,
@ -201,7 +205,7 @@ export default class InfiniteScroll extends Component {
let tempScrollTop = this.scrollTop;
//根据 scrollTop 计算 currentIndex
while (tempScrollTop > 0) {
tempScrollTop -= CONFIG.defaultHeight;
tempScrollTop -= rowHeight;
if (tempScrollTop > 0) {
index += 1;
}