hy-virtual-tree 1.1.18 → 1.1.20

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +17 -2
  2. package/dist/index.js +277 -297
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,18 +1,33 @@
1
1
  ## Changelog
2
2
 
3
+ ### 1.1.20
4
+
5
+ _2025-09-11_
6
+
7
+ - 扩展[VirtualTree] 功能
8
+ (1)修复 CustomRenderFn 函数类型返回对象类型没有内置一层dom元素bug
9
+
10
+ ### 1.1.19
11
+
12
+ _2025-09-10_
13
+
14
+ - 扩展[VirtualTree] 功能
15
+ (1)引入 js-booster 代码到本地,并添加 onRender 回调函数
16
+ (2)CustomRenderFn 函数类型添加 { el: Element, $destroy: Function } 返回类型,其中 $destroy 在节点销毁时调用
17
+
3
18
  ### 1.1.18
4
19
 
5
20
  _2025-09-10_
6
21
 
7
22
  - 扩展[VirtualTree] 功能
8
- (1)修复CustomRenderFn 内置一层dom元素bug
23
+ (1)修复CustomRenderFn 函数类型内置一层dom元素bug
9
24
 
10
25
  ### 1.1.17
11
26
 
12
27
  _2025-09-10_
13
28
 
14
29
  - 扩展[VirtualTree] 功能
15
- (1)CustomRenderFn 内置一层dom元素,兼容vue2的new Vue()挂载问题
30
+ (1)CustomRenderFn 函数类型内置一层dom元素,兼容vue2的new Vue()挂载问题
16
31
 
17
32
  ### 1.1.16
18
33
 
package/dist/index.js CHANGED
@@ -1,259 +1,218 @@
1
- /**
2
- * js-booster - High-performance frontend library
3
- * VirtualScroll - Virtual scrolling implementation
4
- * @version "1.1.4"
5
- * @author https://cg-zhou.top/
6
- * @license MIT
7
- */
8
-
9
1
  class VirtualScroll {
10
- /**
11
- * Create a virtual scroll instance
12
- * @param {Object} options Configuration options
13
- * @param {HTMLElement} options.container Scroll container element
14
- * @param {Array} options.items Data items to display
15
- * @param {number} [options.itemHeight=20] Height of each list item (pixels)
16
- * @param {number} [options.bufferSize=10] Number of buffer items outside the visible area
17
- * @param {Function} [options.renderItem] Custom item rendering function
18
- * @param {Function} [options.renderHeader] Custom header rendering function
19
- * @param {number} [options.maxHeight=26840000] Maximum height in pixels for the content wrapper
20
- */
21
- constructor(options) {
22
- this.container = options.container;
23
- this.items = options.items || [];
24
- this.itemHeight = options.itemHeight || 20;
25
- this.bufferSize = options.bufferSize || 10;
26
- this.customRenderItem = options.renderItem;
27
- this.customRenderHeader = options.renderHeader;
28
- this.maxHeight = options.maxHeight || 26840000; // Add maximum height limit to prevent DOM height overflow
29
-
30
- this.visibleStartIndex = 0;
31
- this.visibleEndIndex = 0;
32
- this.scrollContainer = null;
33
- this.contentWrapper = null;
34
- this.contentContainer = null;
35
- this.totalHeight = this.items.length * this.itemHeight;
36
- this.heightScale = 1; // Height scaling factor
37
-
38
- // If total height exceeds maximum height, calculate scaling factor
39
- if (this.totalHeight > this.maxHeight) {
40
- this.heightScale = this.maxHeight / this.totalHeight;
41
- }
42
- this.initialize();
43
- }
44
-
45
- /**
46
- * Initialize virtual scroll component
47
- * @private
48
- */
49
- initialize() {
50
- // Clear container
51
- this.container.innerHTML = '';
52
-
53
- // Create scroll container
54
- this.scrollContainer = document.createElement('div');
55
- // Add inline styles
56
- Object.assign(this.scrollContainer.style, {
57
- flex: '1',
58
- overflow: 'auto',
59
- position: 'relative',
60
- minHeight: '0',
61
- height: '100%',
62
- boxSizing: 'border-box'
63
- });
64
-
65
- // If there's a custom header render function, render the header
66
- if (this.customRenderHeader) {
67
- const header = this.customRenderHeader();
68
- if (header) {
69
- this.scrollContainer.appendChild(header);
70
- }
71
- }
72
-
73
- // Create content wrapper
74
- this.contentWrapper = document.createElement('div');
75
- // Add inline styles
76
- Object.assign(this.contentWrapper.style, {
77
- position: 'relative',
78
- width: '100%'
79
- });
80
-
81
- // Use scaled height to ensure it doesn't exceed browser limits
82
- const scaledHeight = this.totalHeight * this.heightScale;
83
- this.contentWrapper.style.height = `${scaledHeight}px`;
84
-
85
- // Create content container
86
- this.contentContainer = document.createElement('div');
87
- // Add inline styles
88
- Object.assign(this.contentContainer.style, {
89
- position: 'absolute',
90
- width: '100%',
91
- left: '0'
92
- });
93
-
94
- // Add scroll event listener
95
- this.scrollContainer.addEventListener('scroll', this.handleScroll.bind(this));
96
-
97
- // Assemble DOM
98
- this.contentWrapper.appendChild(this.contentContainer);
99
- this.scrollContainer.appendChild(this.contentWrapper);
100
- this.container.appendChild(this.scrollContainer);
101
-
102
- // Render initial visible items
103
- this.renderVisibleItems(0, Math.min(100, this.items.length));
104
- }
105
-
106
- /**
107
- * Handle scroll event
108
- * @private
109
- */
110
- handleScroll() {
111
- const scrollTop = this.scrollContainer.scrollTop;
112
- const containerHeight = this.scrollContainer.clientHeight;
113
-
114
- // Consider scaling factor in calculations
115
- const realScrollTop = scrollTop / this.heightScale;
116
-
117
- // Calculate visible range
118
- const startIndex = Math.max(0, Math.floor(realScrollTop / this.itemHeight) - this.bufferSize);
119
- const endIndex = Math.min(this.items.length, Math.ceil((realScrollTop + containerHeight / this.heightScale) / this.itemHeight) + this.bufferSize);
120
-
121
- // Only update when visible range changes
122
- if (startIndex !== this.visibleStartIndex || endIndex !== this.visibleEndIndex || endIndex === 0) {
123
- this.renderVisibleItems(startIndex, endIndex);
124
- this.visibleStartIndex = startIndex;
125
- this.visibleEndIndex = endIndex;
126
- }
127
- }
128
-
129
- /**
130
- * Render visible items
131
- * @param {number} startIndex Start index
132
- * @param {number} endIndex End index
133
- * @private
134
- */
135
- renderVisibleItems(startIndex, endIndex) {
136
- // Clear content container
137
- this.contentContainer.innerHTML = '';
138
-
139
- // Set position considering scaling factor
140
- this.contentContainer.style.transform = `translateY(${startIndex * this.itemHeight * this.heightScale}px)`;
141
-
142
- // Render visible items
143
- for (let i = startIndex; i < endIndex; i++) {
144
- const item = this.items[i];
145
- if (this.customRenderItem) {
146
- // Use custom render function
147
- const itemElement = this.customRenderItem(item, i);
148
- if (itemElement) {
149
- // Only set necessary height styles, other styles are determined by the caller
150
- itemElement.style.height = `${this.itemHeight * this.heightScale}px`;
151
- itemElement.style.boxSizing = 'border-box';
152
- itemElement.style.width = '100%';
153
- this.contentContainer.appendChild(itemElement);
2
+ /**
3
+ * Create a virtual scroll instance
4
+ * @param {Object} options Configuration options
5
+ * @param {HTMLElement} options.container Scroll container element
6
+ * @param {Array} options.items Data items to display
7
+ * @param {number} [options.itemHeight=20] Height of each list item (pixels)
8
+ * @param {number} [options.bufferSize=10] Number of buffer items outside the visible area
9
+ * @param {Function} [options.renderItem] Custom item rendering function
10
+ * @param {Function} [options.renderHeader] Custom header rendering function
11
+ * @param {number} [options.maxHeight=26840000] Maximum height in pixels for the content wrapper
12
+ * @param {Function} [options.onRender] 节点刷新回调
13
+ */
14
+ constructor(options) {
15
+ this.container = options.container;
16
+ this.items = options.items || [];
17
+ this.itemHeight = options.itemHeight || 20;
18
+ this.bufferSize = options.bufferSize || 10;
19
+ this.customRenderItem = options.renderItem;
20
+ this.customRenderHeader = options.renderHeader;
21
+ this.maxHeight = options.maxHeight || 26840000; // Add maximum height limit to prevent DOM height overflow
22
+ this.visibleStartIndex = 0;
23
+ this.visibleEndIndex = 0;
24
+ this.scrollContainer = null;
25
+ this.contentWrapper = null;
26
+ this.contentContainer = null;
27
+ this.totalHeight = this.items.length * this.itemHeight;
28
+ this.heightScale = 1; // Height scaling factor
29
+ this._onRender = options.onRender;
30
+ // If total height exceeds maximum height, calculate scaling factor
31
+ if (this.totalHeight > this.maxHeight) {
32
+ this.heightScale = this.maxHeight / this.totalHeight;
33
+ }
34
+ this.initialize();
35
+ }
36
+ /**
37
+ * Initialize virtual scroll component
38
+ * @private
39
+ */
40
+ initialize() {
41
+ // Clear container
42
+ this.container.innerHTML = '';
43
+ // Create scroll container
44
+ this.scrollContainer = document.createElement('div');
45
+ // Add inline styles
46
+ Object.assign(this.scrollContainer.style, {
47
+ flex: '1',
48
+ overflow: 'auto',
49
+ position: 'relative',
50
+ minHeight: '0',
51
+ height: '100%',
52
+ boxSizing: 'border-box'
53
+ });
54
+ // If there's a custom header render function, render the header
55
+ if (this.customRenderHeader) {
56
+ const header = this.customRenderHeader();
57
+ if (header) {
58
+ this.scrollContainer.appendChild(header);
59
+ }
154
60
  }
155
- } else {
156
- // Use default rendering - very simple default implementation
157
- const row = document.createElement('div');
158
- Object.assign(row.style, {
159
- height: `${this.itemHeight * this.heightScale}px`,
160
- width: '100%',
161
- boxSizing: 'border-box',
162
- padding: '8px',
163
- borderBottom: '1px solid #eee'
61
+ // Create content wrapper
62
+ this.contentWrapper = document.createElement('div');
63
+ // Add inline styles
64
+ Object.assign(this.contentWrapper.style, {
65
+ position: 'relative',
66
+ width: '100%'
67
+ });
68
+ // Use scaled height to ensure it doesn't exceed browser limits
69
+ const scaledHeight = this.totalHeight * this.heightScale;
70
+ this.contentWrapper.style.height = `${scaledHeight}px`;
71
+ // Create content container
72
+ this.contentContainer = document.createElement('div');
73
+ // Add inline styles
74
+ Object.assign(this.contentContainer.style, {
75
+ position: 'absolute',
76
+ width: '100%',
77
+ left: '0'
164
78
  });
165
- row.textContent = JSON.stringify(item);
166
- this.contentContainer.appendChild(row);
167
- }
79
+ // Add scroll event listener
80
+ this.scrollContainer.addEventListener('scroll', this.handleScroll.bind(this));
81
+ // Assemble DOM
82
+ this.contentWrapper.appendChild(this.contentContainer);
83
+ this.scrollContainer.appendChild(this.contentWrapper);
84
+ this.container.appendChild(this.scrollContainer);
85
+ // Render initial visible items
86
+ this.renderVisibleItems(0, Math.min(100, this.items.length));
87
+ }
88
+ /**
89
+ * Handle scroll event
90
+ * @private
91
+ */
92
+ handleScroll() {
93
+ const scrollTop = this.scrollContainer.scrollTop;
94
+ const containerHeight = this.scrollContainer.clientHeight;
95
+ // Consider scaling factor in calculations
96
+ const realScrollTop = scrollTop / this.heightScale;
97
+ // Calculate visible range
98
+ const startIndex = Math.max(0, Math.floor(realScrollTop / this.itemHeight) - this.bufferSize);
99
+ const endIndex = Math.min(this.items.length, Math.ceil((realScrollTop + containerHeight / this.heightScale) / this.itemHeight) + this.bufferSize);
100
+ // Only update when visible range changes
101
+ if (startIndex !== this.visibleStartIndex ||
102
+ endIndex !== this.visibleEndIndex ||
103
+ endIndex === 0) {
104
+ this.renderVisibleItems(startIndex, endIndex);
105
+ this.visibleStartIndex = startIndex;
106
+ this.visibleEndIndex = endIndex;
107
+ }
168
108
  }
169
- }
170
-
171
- /**
172
- * Update data items and re-render
173
- * @param {Array} items New data items array
174
- * @public
175
- */
176
- updateItems(items) {
177
- this.items = items || [];
178
- this.totalHeight = this.items.length * this.itemHeight;
179
-
180
- // Recalculate scaling factor
181
- this.heightScale = 1;
182
- if (this.totalHeight > this.maxHeight) {
183
- this.heightScale = this.maxHeight / this.totalHeight;
109
+ /**
110
+ * Render visible items
111
+ * @param {number} startIndex Start index
112
+ * @param {number} endIndex End index
113
+ * @private
114
+ */
115
+ renderVisibleItems(startIndex, endIndex) {
116
+ this._onRender && this._onRender();
117
+ // Clear content container
118
+ this.contentContainer.innerHTML = '';
119
+ // Set position considering scaling factor
120
+ this.contentContainer.style.transform = `translateY(${startIndex * this.itemHeight * this.heightScale}px)`;
121
+ // Render visible items
122
+ for (let i = startIndex; i < endIndex; i++) {
123
+ const item = this.items[i];
124
+ if (this.customRenderItem) {
125
+ // Use custom render function
126
+ const itemElement = this.customRenderItem(item, i);
127
+ if (itemElement) {
128
+ // Only set necessary height styles, other styles are determined by the caller
129
+ itemElement.style.height = `${this.itemHeight * this.heightScale}px`;
130
+ itemElement.style.boxSizing = 'border-box';
131
+ itemElement.style.width = '100%';
132
+ this.contentContainer.appendChild(itemElement);
133
+ }
134
+ }
135
+ else {
136
+ // Use default rendering - very simple default implementation
137
+ const row = document.createElement('div');
138
+ Object.assign(row.style, {
139
+ height: `${this.itemHeight * this.heightScale}px`,
140
+ width: '100%',
141
+ boxSizing: 'border-box',
142
+ padding: '8px',
143
+ borderBottom: '1px solid #eee'
144
+ });
145
+ row.textContent = JSON.stringify(item);
146
+ this.contentContainer.appendChild(row);
147
+ }
148
+ }
184
149
  }
185
-
186
- // Ensure height is set correctly
187
- if (this.contentWrapper) {
188
- this.contentWrapper.style.height = `${this.totalHeight * this.heightScale}px`;
150
+ /**
151
+ * Update data items and re-render
152
+ * @param {Array} items New data items array
153
+ * @public
154
+ */
155
+ updateItems(items) {
156
+ this.items = items || [];
157
+ this.totalHeight = this.items.length * this.itemHeight;
158
+ // Recalculate scaling factor
159
+ this.heightScale = 1;
160
+ if (this.totalHeight > this.maxHeight) {
161
+ this.heightScale = this.maxHeight / this.totalHeight;
162
+ }
163
+ // Ensure height is set correctly
164
+ if (this.contentWrapper) {
165
+ this.contentWrapper.style.height = `${this.totalHeight * this.heightScale}px`;
166
+ }
167
+ this.visibleStartIndex = 0;
168
+ this.visibleEndIndex = 0;
169
+ // Force recalculation of visible items
170
+ this.handleScroll();
171
+ }
172
+ /**
173
+ * Scroll to specified index
174
+ * @param {number} index Index of the item to scroll to
175
+ * @public
176
+ */
177
+ scrollToIndex(index) {
178
+ if (index >= 0 && index < this.items.length) {
179
+ // Apply scaling factor when scrolling
180
+ this.scrollContainer.scrollTop =
181
+ index * this.itemHeight * this.heightScale;
182
+ }
183
+ }
184
+ /**
185
+ * Destroy component, remove event listeners, etc.
186
+ * @public
187
+ */
188
+ destroy() {
189
+ if (this.scrollContainer) {
190
+ this.scrollContainer.removeEventListener('scroll', this.handleScroll);
191
+ }
192
+ if (this.container) {
193
+ this.container.innerHTML = '';
194
+ }
195
+ this.items = null;
196
+ this.container = null;
197
+ this.scrollContainer = null;
198
+ this.contentWrapper = null;
199
+ this.contentContainer = null;
200
+ }
201
+ /**
202
+ * Refresh virtual scroll, re-render current visible items
203
+ * @public
204
+ */
205
+ refresh() {
206
+ this.handleScroll();
207
+ }
208
+ /**
209
+ * Get scroll container element
210
+ * @returns {HTMLElement} Scroll container element
211
+ * @public
212
+ */
213
+ getScrollContainer() {
214
+ return this.scrollContainer;
189
215
  }
190
- this.visibleStartIndex = 0;
191
- this.visibleEndIndex = 0;
192
-
193
- // Force recalculation of visible items
194
- this.handleScroll();
195
- }
196
-
197
- /**
198
- * Scroll to specified index
199
- * @param {number} index Index of the item to scroll to
200
- * @public
201
- */
202
- scrollToIndex(index) {
203
- if (index >= 0 && index < this.items.length) {
204
- // Apply scaling factor when scrolling
205
- this.scrollContainer.scrollTop = index * this.itemHeight * this.heightScale;
206
- }
207
- }
208
-
209
- /**
210
- * Destroy component, remove event listeners, etc.
211
- * @public
212
- */
213
- destroy() {
214
- if (this.scrollContainer) {
215
- this.scrollContainer.removeEventListener('scroll', this.handleScroll);
216
- }
217
- if (this.container) {
218
- this.container.innerHTML = '';
219
- }
220
- this.items = null;
221
- this.container = null;
222
- this.scrollContainer = null;
223
- this.contentWrapper = null;
224
- this.contentContainer = null;
225
- }
226
-
227
- /**
228
- * Refresh virtual scroll, re-render current visible items
229
- * @public
230
- */
231
- refresh() {
232
- this.handleScroll();
233
- }
234
-
235
- /**
236
- * Get scroll container element
237
- * @returns {HTMLElement} Scroll container element
238
- * @public
239
- */
240
- getScrollContainer() {
241
- return this.scrollContainer;
242
- }
243
- }
244
-
245
- /**
246
- * js-booster - High-performance frontend library
247
- * @version "1.1.4"
248
- * @author https://cg-zhou.top/
249
- * @license MIT
250
- */
251
-
252
- // If in browser environment, add to global object
253
- if (typeof window !== 'undefined') {
254
- window.JsBooster = {
255
- VirtualScroll
256
- };
257
216
  }
258
217
 
259
218
  const isString = (e) => typeof e === 'string';
@@ -1399,44 +1358,6 @@ function getContainer(config) {
1399
1358
  }
1400
1359
  return el;
1401
1360
  }
1402
- /** 获取自定义元素函数的值 */
1403
- function customRender(fn, node, options) {
1404
- const { parent, className, defaultFn, inset = false } = options || {};
1405
- let value;
1406
- if (!fn || !isFunction(fn)) {
1407
- value = defaultFn && isFunction(defaultFn) && defaultFn(node.data, node);
1408
- }
1409
- else {
1410
- const dom = fn(node.data, node);
1411
- if (isBoolean(dom) && dom) {
1412
- value = defaultFn && isFunction(defaultFn) && defaultFn(node.data, node);
1413
- }
1414
- else if (isElement(dom) && inset) {
1415
- value = document.createElement('div');
1416
- className && value.classList.add(className);
1417
- value.appendChild(dom);
1418
- }
1419
- else {
1420
- value = dom;
1421
- }
1422
- }
1423
- if (isEmpty(value))
1424
- return;
1425
- if (isElement(value)) {
1426
- className && value.classList.add(className);
1427
- if (parent) {
1428
- parent.appendChild(value);
1429
- }
1430
- return value;
1431
- }
1432
- const el = document.createElement('div');
1433
- el.innerHTML = value;
1434
- className && el.classList.add(className);
1435
- if (parent) {
1436
- parent.appendChild(el);
1437
- }
1438
- return el;
1439
- }
1440
1361
  class VirtualTree {
1441
1362
  _virtualScroll;
1442
1363
  _el = null;
@@ -1462,6 +1383,7 @@ class VirtualTree {
1462
1383
  _hiddenExpandIconKeySet = new Set(); // 隐藏展开图标
1463
1384
  _hiddenNodeKeySet = new Set(); // 隐藏的key
1464
1385
  _flattenTree = []; // 平铺树列表
1386
+ _destroyDomSet = new Set();
1465
1387
  _handleMethod;
1466
1388
  _filterMethod;
1467
1389
  _isForceHiddenExpandIcon;
@@ -1750,6 +1672,58 @@ class VirtualTree {
1750
1672
  this._onNodeExpand && this._onNodeExpand(node.data, node);
1751
1673
  }
1752
1674
  }
1675
+ /** 获取自定义元素函数的值 */
1676
+ _customRender(fn, node, options) {
1677
+ const { parent, className, defaultFn, inset = false } = options || {};
1678
+ let value, el, $destroy;
1679
+ if (!fn || !isFunction(fn)) {
1680
+ value = defaultFn && isFunction(defaultFn) && defaultFn(node.data, node);
1681
+ }
1682
+ else {
1683
+ let dom = fn(node.data, node);
1684
+ if (isObject(dom) && dom.el) {
1685
+ $destroy = dom.$destroy;
1686
+ dom = dom.el;
1687
+ }
1688
+ if (isBoolean(dom) && dom) {
1689
+ value = defaultFn && isFunction(defaultFn) && defaultFn(node.data, node);
1690
+ }
1691
+ else if (isElement(dom) && inset) {
1692
+ value = document.createElement('div');
1693
+ className && value.classList.add(className);
1694
+ value.appendChild(dom);
1695
+ }
1696
+ else {
1697
+ value = dom;
1698
+ }
1699
+ }
1700
+ if (isObject(value) && value.el) {
1701
+ $destroy = value.$destroy;
1702
+ value = value.el;
1703
+ }
1704
+ if (isEmpty(value))
1705
+ return;
1706
+ this._destroyDomSet.add(() => {
1707
+ $destroy && $destroy();
1708
+ $destroy = null;
1709
+ value = null;
1710
+ el = null;
1711
+ });
1712
+ if (isElement(value)) {
1713
+ className && value.classList.add(className);
1714
+ if (parent) {
1715
+ parent.appendChild(value);
1716
+ }
1717
+ return value;
1718
+ }
1719
+ el = document.createElement('div');
1720
+ el.innerHTML = value;
1721
+ className && el.classList.add(className);
1722
+ if (parent) {
1723
+ parent.appendChild(el);
1724
+ }
1725
+ return el;
1726
+ }
1753
1727
  /** 渲染 */
1754
1728
  async _render(config) {
1755
1729
  if (this._virtualScroll)
@@ -1837,14 +1811,14 @@ class VirtualTree {
1837
1811
  let statusSlot, rightSlot;
1838
1812
  // 是否显示状态
1839
1813
  if (this._props.showStatus) {
1840
- statusSlot = customRender(config.renderStatus, item, {
1814
+ statusSlot = this._customRender(config.renderStatus, item, {
1841
1815
  inset: true,
1842
1816
  className: 'hy-tree-node__status',
1843
1817
  defaultFn: (data, node) => useStatus(config, data)
1844
1818
  });
1845
1819
  }
1846
1820
  // 右侧内容
1847
- rightSlot = customRender(config.renderRight, item, { inset: true, className: 'hy-tree-node__right-content' });
1821
+ rightSlot = this._customRender(config.renderRight, item, { inset: true, className: 'hy-tree-node__right-content' });
1848
1822
  if (!isElement(statusSlot) && !isElement(rightSlot))
1849
1823
  return;
1850
1824
  const el = document.createElement('div');
@@ -1937,19 +1911,19 @@ class VirtualTree {
1937
1911
  }
1938
1912
  }
1939
1913
  // 整个节点内容
1940
- customRender(config.renderItem, item, {
1914
+ this._customRender(config.renderItem, item, {
1941
1915
  inset: true,
1942
1916
  parent: content,
1943
1917
  className: 'hy-tree-node__node-content',
1944
1918
  defaultFn: (data, node) => {
1945
1919
  // 图标
1946
- customRender(config.renderIcon, node, { inset: true, parent: content, className: 'hy-tree-icon', defaultFn: generateIcon });
1920
+ this._customRender(config.renderIcon, node, { inset: true, parent: content, className: 'hy-tree-icon', defaultFn: generateIcon });
1947
1921
  // 内容
1948
- customRender(config.renderContent, node, { inset: true, parent: content, className: 'hy-tree-node__content', defaultFn: generateContent });
1922
+ this._customRender(config.renderContent, node, { inset: true, parent: content, className: 'hy-tree-node__content', defaultFn: generateContent });
1949
1923
  // 统计
1950
- customRender(generateStats, node, { parent: content });
1924
+ this._customRender(generateStats, node, { parent: content });
1951
1925
  // 右侧内容
1952
- customRender(generateRight, node, { parent: content });
1926
+ this._customRender(generateRight, node, { parent: content });
1953
1927
  }
1954
1928
  });
1955
1929
  nodeContainer.appendChild(content);
@@ -2030,7 +2004,13 @@ class VirtualTree {
2030
2004
  items: this._flattenTree,
2031
2005
  itemHeight: config.itemHeight + (config.itemGap || 0),
2032
2006
  bufferSize: config.bufferSize,
2033
- renderItem
2007
+ renderItem,
2008
+ onRender: () => {
2009
+ for (const $destroy of this._destroyDomSet) {
2010
+ $destroy && $destroy();
2011
+ }
2012
+ this._destroyDomSet.clear();
2013
+ }
2034
2014
  });
2035
2015
  config.onLoad && config.onLoad();
2036
2016
  }
@@ -2176,4 +2156,4 @@ class VirtualTree {
2176
2156
  };
2177
2157
  }
2178
2158
 
2179
- export { VirtualTree, isArray, isBoolean, isElement, isEmpty, isFunction, isNull, isNumber, isObject, isString, isUndefined };
2159
+ export { VirtualScroll, VirtualTree, isArray, isBoolean, isElement, isEmpty, isFunction, isNull, isNumber, isObject, isString, isUndefined };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hy-virtual-tree",
3
- "version": "1.1.18",
3
+ "version": "1.1.20",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite",