pixuireactcomponents 1.5.24 → 1.5.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { h, Component, JSX } from 'preact';
|
|
2
|
+
interface VirtualListScrollProps {
|
|
3
|
+
/**
|
|
4
|
+
* 滚动回弹类型, 具体表现为是否可以拖动超过内容大小值
|
|
5
|
+
* - elastic: 触顶触底会回弹
|
|
6
|
+
* - clamped: 触顶触底不回弹
|
|
7
|
+
* - 默认值:elastic
|
|
8
|
+
*/
|
|
9
|
+
movementType?: 'elastic' | 'clamped';
|
|
10
|
+
/**
|
|
11
|
+
* 滑动灵敏度
|
|
12
|
+
* - 值越大滑动越灵敏, 滑动距离会乘上滑动灵敏度
|
|
13
|
+
* - 默认值:1
|
|
14
|
+
*/
|
|
15
|
+
scrollSensitivity?: number;
|
|
16
|
+
/**
|
|
17
|
+
* 是否有惯性
|
|
18
|
+
* - true: 滑动后会有惯性滚动
|
|
19
|
+
* - false: 滑动后立即停止
|
|
20
|
+
* - 默认值:true
|
|
21
|
+
*/
|
|
22
|
+
inertia?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* 惯性函数版本
|
|
25
|
+
* - 1: 倾向于unity的惯性效果
|
|
26
|
+
* - 2: 倾向于ue的惯性效果
|
|
27
|
+
* - 默认值:2
|
|
28
|
+
*/
|
|
29
|
+
inertiaVersion?: number;
|
|
30
|
+
/**
|
|
31
|
+
* 惯性衰减率, 仅在inertiaVersion为1时生效
|
|
32
|
+
* - 取值范围:0(立即停止)到 1(无减速)
|
|
33
|
+
* - 默认值:0.135
|
|
34
|
+
*/
|
|
35
|
+
decelerationRate?: number;
|
|
36
|
+
/**
|
|
37
|
+
* 静态速度阻力, 仅在inertiaVersion为2时生效
|
|
38
|
+
* - 每秒速度的固定衰减值
|
|
39
|
+
* - 默认值:100
|
|
40
|
+
*/
|
|
41
|
+
staticVelocityDrag?: number;
|
|
42
|
+
/**
|
|
43
|
+
* 摩擦系数, 仅在inertiaVersion为2时生效
|
|
44
|
+
* - 每秒速度的动态衰减值, 当前速度*frictionCoefficient
|
|
45
|
+
* - 默认值:2.0
|
|
46
|
+
*/
|
|
47
|
+
frictionCoefficient?: number;
|
|
48
|
+
}
|
|
49
|
+
interface VirtualListProps {
|
|
50
|
+
/** 布局方向 - horizontal: 水平布局, vertical: 垂直布局 */
|
|
51
|
+
layout: 'horizontal' | 'vertical';
|
|
52
|
+
/** 渲染列表项的函数,接收索引返回JSX元素 */
|
|
53
|
+
renderItemFunc: (index: number) => JSX.Element;
|
|
54
|
+
/** 每个列表项的尺寸(水平布局时为宽度,垂直布局时为高度) */
|
|
55
|
+
itemSize: number;
|
|
56
|
+
/** 列表项总数 */
|
|
57
|
+
itemCount: number;
|
|
58
|
+
/** 可视区域宽度 */
|
|
59
|
+
width: any;
|
|
60
|
+
/** 可视区域高度 */
|
|
61
|
+
height: any;
|
|
62
|
+
/** 缓存的列表项数量(会在可视区域前后多渲染的数量) */
|
|
63
|
+
cacheSize: number;
|
|
64
|
+
/** 自定义样式, 会添加到组件根节点 */
|
|
65
|
+
style?: {};
|
|
66
|
+
/** 是否还有更多数据可以加载, 返回false会阻止后续判断是否loadMore */
|
|
67
|
+
hasMore?: () => boolean;
|
|
68
|
+
/** 触底阈值, 到达后会调用loadMore, 默认为itemSize*2 */
|
|
69
|
+
touchBottomThreshold?: number;
|
|
70
|
+
/** 加载更多数据的回调函数 */
|
|
71
|
+
loadMore?: () => Promise<void>;
|
|
72
|
+
/** 顶部区域组件 */
|
|
73
|
+
TopArea?: h.JSX.Element;
|
|
74
|
+
/** 顶部区域尺寸 */
|
|
75
|
+
topAreaSize?: number;
|
|
76
|
+
/** 滚动相关配置属性 */
|
|
77
|
+
scrollProps?: VirtualListScrollProps;
|
|
78
|
+
}
|
|
79
|
+
interface VirtualListState {
|
|
80
|
+
start: number;
|
|
81
|
+
end: number;
|
|
82
|
+
listHeight: number;
|
|
83
|
+
}
|
|
84
|
+
export declare class VirtualList extends Component<VirtualListProps, VirtualListState> {
|
|
85
|
+
itemCache: Array<{
|
|
86
|
+
vNode: h.JSX.Element;
|
|
87
|
+
isValid: any;
|
|
88
|
+
ref: any;
|
|
89
|
+
}>;
|
|
90
|
+
style: {
|
|
91
|
+
position?: string;
|
|
92
|
+
height?: number;
|
|
93
|
+
width?: any;
|
|
94
|
+
};
|
|
95
|
+
ref: any;
|
|
96
|
+
listSize: number;
|
|
97
|
+
/** 列表总长度 */
|
|
98
|
+
protected listHeight: number;
|
|
99
|
+
/** 触底阈值 */
|
|
100
|
+
protected touchBottomThreshold: number;
|
|
101
|
+
/** 视窗可见数量 */
|
|
102
|
+
protected itemCount: number;
|
|
103
|
+
/** 是否正在加载更多 */
|
|
104
|
+
protected isLoading: boolean;
|
|
105
|
+
/** 视窗可见数量 */
|
|
106
|
+
protected visibleCount: number;
|
|
107
|
+
/** 顶部区域高度 */
|
|
108
|
+
protected topHeight: number;
|
|
109
|
+
constructor(props: VirtualListProps);
|
|
110
|
+
componentDidMount(): void;
|
|
111
|
+
shouldComponentUpdate(nextProps: Readonly<VirtualListProps>, nextState: Readonly<VirtualListState>, nextContext: any): boolean;
|
|
112
|
+
componentWillReceiveProps(nextProps: Readonly<VirtualListProps>): void;
|
|
113
|
+
onScroll: (e: Event) => void;
|
|
114
|
+
render(): h.JSX.Element;
|
|
115
|
+
}
|
|
116
|
+
export {};
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
var __extends = (this && this.__extends) || (function () {
|
|
2
|
+
var extendStatics = function (d, b) {
|
|
3
|
+
extendStatics = Object.setPrototypeOf ||
|
|
4
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
5
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
6
|
+
return extendStatics(d, b);
|
|
7
|
+
};
|
|
8
|
+
return function (d, b) {
|
|
9
|
+
if (typeof b !== "function" && b !== null)
|
|
10
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
11
|
+
extendStatics(d, b);
|
|
12
|
+
function __() { this.constructor = d; }
|
|
13
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
14
|
+
};
|
|
15
|
+
})();
|
|
16
|
+
var __assign = (this && this.__assign) || function () {
|
|
17
|
+
__assign = Object.assign || function(t) {
|
|
18
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
19
|
+
s = arguments[i];
|
|
20
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
21
|
+
t[p] = s[p];
|
|
22
|
+
}
|
|
23
|
+
return t;
|
|
24
|
+
};
|
|
25
|
+
return __assign.apply(this, arguments);
|
|
26
|
+
};
|
|
27
|
+
import { h, Component, createRef } from 'preact';
|
|
28
|
+
var VirtualListItem = /** @class */ (function (_super) {
|
|
29
|
+
__extends(VirtualListItem, _super);
|
|
30
|
+
function VirtualListItem(props) {
|
|
31
|
+
var _this = _super.call(this, props) || this;
|
|
32
|
+
_this.updateIndex = function (index) {
|
|
33
|
+
_this.setState({ index: index });
|
|
34
|
+
};
|
|
35
|
+
_this.updateValid = function (isValid) {
|
|
36
|
+
_this.setState({ isValid: isValid });
|
|
37
|
+
};
|
|
38
|
+
_this.updateChildren = function (child) {
|
|
39
|
+
_this.setState({ child: child });
|
|
40
|
+
};
|
|
41
|
+
_this.state = {
|
|
42
|
+
index: props.index,
|
|
43
|
+
isValid: true,
|
|
44
|
+
child: props.child,
|
|
45
|
+
};
|
|
46
|
+
return _this;
|
|
47
|
+
}
|
|
48
|
+
VirtualListItem.prototype.render = function () {
|
|
49
|
+
var VirtualListStyle = {};
|
|
50
|
+
if (this.props.layout === 'horizontal') {
|
|
51
|
+
VirtualListStyle = {
|
|
52
|
+
position: 'absolute',
|
|
53
|
+
left: this.state.index * this.props.itemMainSize,
|
|
54
|
+
width: this.props.itemMainSize,
|
|
55
|
+
height: this.props.itemCrossSize,
|
|
56
|
+
display: this.state.isValid ? 'flex' : 'none',
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
VirtualListStyle = {
|
|
61
|
+
position: 'absolute',
|
|
62
|
+
top: this.state.index * this.props.itemMainSize,
|
|
63
|
+
height: this.props.itemMainSize,
|
|
64
|
+
width: this.props.itemCrossSize,
|
|
65
|
+
display: this.state.isValid ? 'flex' : 'none',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return h("div", { style: VirtualListStyle }, this.state.child);
|
|
69
|
+
};
|
|
70
|
+
return VirtualListItem;
|
|
71
|
+
}(Component));
|
|
72
|
+
var VirtualList = /** @class */ (function (_super) {
|
|
73
|
+
__extends(VirtualList, _super);
|
|
74
|
+
function VirtualList(props) {
|
|
75
|
+
var _this = _super.call(this, props) || this;
|
|
76
|
+
_this.itemCache = [];
|
|
77
|
+
_this.onScroll = function (e) {
|
|
78
|
+
var target = e.target;
|
|
79
|
+
var scrollTop = _this.props.layout === 'horizontal' ? target.scrollLeft : target.scrollTop;
|
|
80
|
+
var itemSize = _this.props.itemSize;
|
|
81
|
+
var start = Math.floor(scrollTop / itemSize);
|
|
82
|
+
var end = start + _this.visibleCount;
|
|
83
|
+
_this.setState({ start: start, end: end });
|
|
84
|
+
// 判断触底逻辑
|
|
85
|
+
if (_this.isLoading || !_this.props.hasMore)
|
|
86
|
+
return;
|
|
87
|
+
if (!_this.props.hasMore())
|
|
88
|
+
return;
|
|
89
|
+
var clientHeight = target.clientHeight;
|
|
90
|
+
var clientSize = _this.state.listHeight;
|
|
91
|
+
if (scrollTop + clientHeight + _this.touchBottomThreshold > clientSize) {
|
|
92
|
+
_this.isLoading = true;
|
|
93
|
+
if (!_this.props.loadMore) {
|
|
94
|
+
_this.isLoading = false;
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
_this.props.loadMore().then(function () {
|
|
98
|
+
_this.isLoading = false;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
_this.style = {
|
|
103
|
+
position: 'absolute',
|
|
104
|
+
height: props.itemSize,
|
|
105
|
+
width: props.width,
|
|
106
|
+
};
|
|
107
|
+
_this.topHeight = _this.props.topAreaSize || 0;
|
|
108
|
+
_this.listHeight = props.itemCount * props.itemSize + _this.topHeight;
|
|
109
|
+
_this.state = {
|
|
110
|
+
start: 0,
|
|
111
|
+
end: 0,
|
|
112
|
+
listHeight: _this.listHeight,
|
|
113
|
+
};
|
|
114
|
+
_this.ref = createRef();
|
|
115
|
+
_this.visibleCount = 0;
|
|
116
|
+
_this.listSize = 0;
|
|
117
|
+
_this.itemCount = 0;
|
|
118
|
+
_this.touchBottomThreshold = (props.touchBottomThreshold != null || props.touchBottomThreshold != undefined) ? props.touchBottomThreshold : props.itemSize * 2;
|
|
119
|
+
_this.isLoading = false;
|
|
120
|
+
return _this;
|
|
121
|
+
}
|
|
122
|
+
VirtualList.prototype.componentDidMount = function () {
|
|
123
|
+
if (this.ref.current) {
|
|
124
|
+
if (this.props.layout === 'horizontal') {
|
|
125
|
+
this.listSize = this.ref.current.getBoundingClientRect().width;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
this.listSize = this.ref.current.getBoundingClientRect().height;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
this.visibleCount = Math.ceil(this.listSize / this.props.itemSize);
|
|
132
|
+
this.itemCount = this.visibleCount;
|
|
133
|
+
for (var i = 0; i < this.itemCount + this.props.cacheSize * 2; i++) {
|
|
134
|
+
var ref = createRef();
|
|
135
|
+
var itemCrossSize = this.props.layout === 'horizontal' ? this.props.height : this.props.width;
|
|
136
|
+
var item = {
|
|
137
|
+
vNode: (h(VirtualListItem, { layout: this.props.layout, index: i, key: i, ref: ref, itemMainSize: this.props.itemSize, itemCrossSize: itemCrossSize, child: this.props.renderItemFunc(i) })),
|
|
138
|
+
isValid: false,
|
|
139
|
+
ref: ref,
|
|
140
|
+
};
|
|
141
|
+
this.itemCache.push(item);
|
|
142
|
+
this.forceUpdate();
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
VirtualList.prototype.shouldComponentUpdate = function (nextProps, nextState, nextContext) {
|
|
146
|
+
return this.state.start !== nextState.start || this.state.end !== nextState.end || this.props !== nextProps;
|
|
147
|
+
};
|
|
148
|
+
VirtualList.prototype.componentWillReceiveProps = function (nextProps) {
|
|
149
|
+
if (nextProps.itemCount === this.props.itemCount)
|
|
150
|
+
return;
|
|
151
|
+
// 切换显示列表
|
|
152
|
+
if ((nextProps.itemCount !== this.itemCount && this.props.itemCount === 0) || nextProps.itemCount === 0) {
|
|
153
|
+
this.setState({
|
|
154
|
+
start: 0,
|
|
155
|
+
end: Math.min(this.state.start + this.visibleCount, nextProps.itemCount),
|
|
156
|
+
listHeight: nextProps.itemCount * nextProps.itemSize + this.topHeight,
|
|
157
|
+
});
|
|
158
|
+
this.ref.scrollTop = 0;
|
|
159
|
+
this.forceUpdate();
|
|
160
|
+
}
|
|
161
|
+
if (nextProps.itemCount !== this.props.itemCount) {
|
|
162
|
+
this.setState({
|
|
163
|
+
listHeight: nextProps.itemCount * nextProps.itemSize + this.topHeight,
|
|
164
|
+
});
|
|
165
|
+
this.forceUpdate();
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
VirtualList.prototype.render = function () {
|
|
169
|
+
var _this = this;
|
|
170
|
+
var start = Math.max(0, this.state.start - this.props.cacheSize);
|
|
171
|
+
var end = Math.min(this.state.end + this.props.cacheSize, this.props.itemCount);
|
|
172
|
+
//diff
|
|
173
|
+
var currentIndexList = new Set();
|
|
174
|
+
for (var i = start; i < end; i++) {
|
|
175
|
+
currentIndexList.add(i);
|
|
176
|
+
}
|
|
177
|
+
for (var i = 0; i < this.itemCache.length; i++) {
|
|
178
|
+
var item = this.itemCache[i];
|
|
179
|
+
item.isValid = false;
|
|
180
|
+
if (item.ref.current) {
|
|
181
|
+
var index = item.ref.current.state.index;
|
|
182
|
+
if (currentIndexList.has(index)) {
|
|
183
|
+
item.isValid = true;
|
|
184
|
+
currentIndexList.delete(index);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
currentIndexList.forEach(function (index) {
|
|
189
|
+
// create new
|
|
190
|
+
for (var i = 0; i < _this.itemCache.length; i++) {
|
|
191
|
+
var item = _this.itemCache[i];
|
|
192
|
+
if (item.isValid === false) {
|
|
193
|
+
if (item.ref.current) {
|
|
194
|
+
item.ref.current.updateValid(true);
|
|
195
|
+
item.ref.current.updateIndex(index);
|
|
196
|
+
item.ref.current.updateChildren(_this.props.renderItemFunc(index));
|
|
197
|
+
}
|
|
198
|
+
item.isValid = true;
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
var VirtualListStyle = {};
|
|
204
|
+
if (this.props.layout === 'horizontal') {
|
|
205
|
+
VirtualListStyle = {
|
|
206
|
+
display: 'flex',
|
|
207
|
+
flexDirection: 'row',
|
|
208
|
+
flexShrink: 0,
|
|
209
|
+
width: this.props.itemSize * this.props.itemCount,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
VirtualListStyle = {
|
|
214
|
+
display: 'flex',
|
|
215
|
+
flexDirection: 'column',
|
|
216
|
+
flexShrink: 0,
|
|
217
|
+
height: "".concat(this.state.listHeight, "px"),
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/* 兼容双问号 */
|
|
221
|
+
var movementType = 'elastic';
|
|
222
|
+
if (this.props.scrollProps && this.props.scrollProps.movementType !== null && this.props.scrollProps.movementType !== undefined) {
|
|
223
|
+
movementType = this.props.scrollProps.movementType;
|
|
224
|
+
}
|
|
225
|
+
var scrollSensitivity = 1;
|
|
226
|
+
if (this.props.scrollProps && this.props.scrollProps.scrollSensitivity !== null && this.props.scrollProps.scrollSensitivity !== undefined) {
|
|
227
|
+
scrollSensitivity = this.props.scrollProps.scrollSensitivity;
|
|
228
|
+
}
|
|
229
|
+
var inertiaVersion = 2;
|
|
230
|
+
if (this.props.scrollProps && this.props.scrollProps.inertiaVersion !== null && this.props.scrollProps.inertiaVersion !== undefined) {
|
|
231
|
+
inertiaVersion = this.props.scrollProps.inertiaVersion;
|
|
232
|
+
}
|
|
233
|
+
var decelerationRate = 0.135;
|
|
234
|
+
if (this.props.scrollProps && this.props.scrollProps.decelerationRate !== null && this.props.scrollProps.decelerationRate !== undefined) {
|
|
235
|
+
decelerationRate = this.props.scrollProps.decelerationRate;
|
|
236
|
+
}
|
|
237
|
+
var staticVelocityDrag = 100;
|
|
238
|
+
if (this.props.scrollProps && this.props.scrollProps.staticVelocityDrag !== null && this.props.scrollProps.staticVelocityDrag !== undefined) {
|
|
239
|
+
staticVelocityDrag = this.props.scrollProps.staticVelocityDrag;
|
|
240
|
+
}
|
|
241
|
+
var frictionCoefficient = 2.0;
|
|
242
|
+
if (this.props.scrollProps && this.props.scrollProps.frictionCoefficient !== null && this.props.scrollProps.frictionCoefficient !== undefined) {
|
|
243
|
+
frictionCoefficient = this.props.scrollProps.frictionCoefficient;
|
|
244
|
+
}
|
|
245
|
+
return (h("div", { key: "VirtualListRoot", id: 'VirtualListRoot', "movement-type": movementType, "scroll-sensitivity": scrollSensitivity, "inertia-version": inertiaVersion, "deceleration-rate": decelerationRate, "static-velocity-drag": staticVelocityDrag, "friction-coefficient": frictionCoefficient, ref: this.ref, onScroll: this.onScroll, style: __assign({ position: 'relative', overflow: 'scroll', flexDirection: this.props.layout === 'horizontal' ? 'row' : 'column', width: this.props.width, height: this.props.height }, this.props.style) },
|
|
246
|
+
this.props.TopArea,
|
|
247
|
+
h("div", { key: "VirtualList", id: 'VirtualList', style: VirtualListStyle }, this.itemCache.map(function (item) { return item.vNode; }))));
|
|
248
|
+
};
|
|
249
|
+
return VirtualList;
|
|
250
|
+
}(Component));
|
|
251
|
+
export { VirtualList };
|