vxe-pc-ui 4.7.5 → 4.7.7

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 (197) hide show
  1. package/es/icon/style.css +1 -1
  2. package/es/language/ar-EG.js +19 -1
  3. package/es/language/de-DE.js +19 -1
  4. package/es/language/en-US.js +20 -2
  5. package/es/language/es-ES.js +19 -1
  6. package/es/language/fr-FR.js +19 -1
  7. package/es/language/hu-HU.js +19 -1
  8. package/es/language/hy-AM.js +18 -0
  9. package/es/language/id-ID.js +19 -1
  10. package/es/language/it-IT.js +19 -1
  11. package/es/language/ja-JP.js +19 -1
  12. package/es/language/ko-KR.js +19 -1
  13. package/es/language/ms-MY.js +19 -1
  14. package/es/language/nb-NO.js +19 -1
  15. package/es/language/pt-BR.js +19 -1
  16. package/es/language/ru-RU.js +19 -1
  17. package/es/language/th-TH.js +19 -1
  18. package/es/language/ug-CN.js +19 -1
  19. package/es/language/uk-UA.js +19 -1
  20. package/es/language/uz-UZ.js +19 -1
  21. package/es/language/vi-VN.js +19 -1
  22. package/es/language/zh-CHT.js +19 -1
  23. package/es/language/zh-CN.js +18 -0
  24. package/es/list/src/list.js +1 -1
  25. package/es/select/src/select.js +135 -42
  26. package/es/select/style.css +21 -0
  27. package/es/select/style.min.css +1 -1
  28. package/es/style.css +1 -1
  29. package/es/style.min.css +1 -1
  30. package/es/tree/src/tree.js +924 -407
  31. package/es/tree/src/util.js +32 -0
  32. package/es/tree/style.css +29 -26
  33. package/es/tree/style.min.css +1 -1
  34. package/es/tree-select/src/tree-select.js +227 -18
  35. package/es/tree-select/style.css +36 -1
  36. package/es/tree-select/style.min.css +1 -1
  37. package/es/ui/index.js +19 -3
  38. package/es/ui/src/dom.js +9 -0
  39. package/es/ui/src/log.js +1 -1
  40. package/es/vxe-select/style.css +21 -0
  41. package/es/vxe-select/style.min.css +1 -1
  42. package/es/vxe-tree/style.css +29 -26
  43. package/es/vxe-tree/style.min.css +1 -1
  44. package/es/vxe-tree-select/style.css +36 -1
  45. package/es/vxe-tree-select/style.min.css +1 -1
  46. package/lib/icon/style/style.css +1 -1
  47. package/lib/icon/style/style.min.css +1 -1
  48. package/lib/index.umd.js +1512 -530
  49. package/lib/index.umd.min.js +1 -1
  50. package/lib/language/ar-EG.js +19 -1
  51. package/lib/language/ar-EG.min.js +1 -1
  52. package/lib/language/ar-EG.umd.js +19 -1
  53. package/lib/language/de-DE.js +19 -1
  54. package/lib/language/de-DE.min.js +1 -1
  55. package/lib/language/de-DE.umd.js +19 -1
  56. package/lib/language/en-US.js +20 -2
  57. package/lib/language/en-US.min.js +1 -1
  58. package/lib/language/en-US.umd.js +20 -2
  59. package/lib/language/es-ES.js +19 -1
  60. package/lib/language/es-ES.min.js +1 -1
  61. package/lib/language/es-ES.umd.js +19 -1
  62. package/lib/language/fr-FR.js +19 -1
  63. package/lib/language/fr-FR.min.js +1 -1
  64. package/lib/language/fr-FR.umd.js +19 -1
  65. package/lib/language/hu-HU.js +19 -1
  66. package/lib/language/hu-HU.min.js +1 -1
  67. package/lib/language/hu-HU.umd.js +19 -1
  68. package/lib/language/hy-AM.js +18 -0
  69. package/lib/language/hy-AM.min.js +1 -1
  70. package/lib/language/hy-AM.umd.js +18 -0
  71. package/lib/language/id-ID.js +19 -1
  72. package/lib/language/id-ID.min.js +1 -1
  73. package/lib/language/id-ID.umd.js +19 -1
  74. package/lib/language/it-IT.js +19 -1
  75. package/lib/language/it-IT.min.js +1 -1
  76. package/lib/language/it-IT.umd.js +19 -1
  77. package/lib/language/ja-JP.js +19 -1
  78. package/lib/language/ja-JP.min.js +1 -1
  79. package/lib/language/ja-JP.umd.js +19 -1
  80. package/lib/language/ko-KR.js +19 -1
  81. package/lib/language/ko-KR.min.js +1 -1
  82. package/lib/language/ko-KR.umd.js +19 -1
  83. package/lib/language/ms-MY.js +19 -1
  84. package/lib/language/ms-MY.min.js +1 -1
  85. package/lib/language/ms-MY.umd.js +19 -1
  86. package/lib/language/nb-NO.js +19 -1
  87. package/lib/language/nb-NO.min.js +1 -1
  88. package/lib/language/nb-NO.umd.js +19 -1
  89. package/lib/language/pt-BR.js +19 -1
  90. package/lib/language/pt-BR.min.js +1 -1
  91. package/lib/language/pt-BR.umd.js +19 -1
  92. package/lib/language/ru-RU.js +19 -1
  93. package/lib/language/ru-RU.min.js +1 -1
  94. package/lib/language/ru-RU.umd.js +19 -1
  95. package/lib/language/th-TH.js +19 -1
  96. package/lib/language/th-TH.min.js +1 -1
  97. package/lib/language/th-TH.umd.js +19 -1
  98. package/lib/language/ug-CN.js +19 -1
  99. package/lib/language/ug-CN.min.js +1 -1
  100. package/lib/language/ug-CN.umd.js +19 -1
  101. package/lib/language/uk-UA.js +19 -1
  102. package/lib/language/uk-UA.min.js +1 -1
  103. package/lib/language/uk-UA.umd.js +19 -1
  104. package/lib/language/uz-UZ.js +19 -1
  105. package/lib/language/uz-UZ.min.js +1 -1
  106. package/lib/language/uz-UZ.umd.js +19 -1
  107. package/lib/language/vi-VN.js +19 -1
  108. package/lib/language/vi-VN.min.js +1 -1
  109. package/lib/language/vi-VN.umd.js +19 -1
  110. package/lib/language/zh-CHT.js +19 -1
  111. package/lib/language/zh-CHT.min.js +1 -1
  112. package/lib/language/zh-CHT.umd.js +19 -1
  113. package/lib/language/zh-CN.js +18 -0
  114. package/lib/language/zh-CN.min.js +1 -1
  115. package/lib/language/zh-CN.umd.js +18 -0
  116. package/lib/list/src/list.js +1 -1
  117. package/lib/list/src/list.min.js +1 -1
  118. package/lib/select/src/select.js +139 -44
  119. package/lib/select/src/select.min.js +1 -1
  120. package/lib/select/style/style.css +21 -0
  121. package/lib/select/style/style.min.css +1 -1
  122. package/lib/style.css +1 -1
  123. package/lib/style.min.css +1 -1
  124. package/lib/tree/src/tree.js +1154 -572
  125. package/lib/tree/src/tree.min.js +1 -1
  126. package/lib/tree/src/util.js +51 -0
  127. package/lib/tree/src/util.min.js +1 -0
  128. package/lib/tree/style/style.css +29 -26
  129. package/lib/tree/style/style.min.css +1 -1
  130. package/lib/tree-select/src/tree-select.js +237 -21
  131. package/lib/tree-select/src/tree-select.min.js +1 -1
  132. package/lib/tree-select/style/style.css +36 -1
  133. package/lib/tree-select/style/style.min.css +1 -1
  134. package/lib/ui/index.js +19 -3
  135. package/lib/ui/index.min.js +1 -1
  136. package/lib/ui/src/dom.js +10 -0
  137. package/lib/ui/src/dom.min.js +1 -1
  138. package/lib/ui/src/log.js +1 -1
  139. package/lib/ui/src/log.min.js +1 -1
  140. package/lib/vxe-select/style/style.css +21 -0
  141. package/lib/vxe-select/style/style.min.css +1 -1
  142. package/lib/vxe-tree/style/style.css +29 -26
  143. package/lib/vxe-tree/style/style.min.css +1 -1
  144. package/lib/vxe-tree-select/style/style.css +36 -1
  145. package/lib/vxe-tree-select/style/style.min.css +1 -1
  146. package/package.json +1 -1
  147. package/packages/language/ar-EG.ts +19 -1
  148. package/packages/language/de-DE.ts +19 -1
  149. package/packages/language/en-US.ts +20 -2
  150. package/packages/language/es-ES.ts +19 -1
  151. package/packages/language/fr-FR.ts +19 -1
  152. package/packages/language/hu-HU.ts +19 -1
  153. package/packages/language/hy-AM.ts +18 -0
  154. package/packages/language/id-ID.ts +19 -1
  155. package/packages/language/it-IT.ts +19 -1
  156. package/packages/language/ja-JP.ts +19 -1
  157. package/packages/language/ko-KR.ts +19 -1
  158. package/packages/language/ms-MY.ts +19 -1
  159. package/packages/language/nb-NO.ts +19 -1
  160. package/packages/language/pt-BR.ts +19 -1
  161. package/packages/language/ru-RU.ts +19 -1
  162. package/packages/language/th-TH.ts +19 -1
  163. package/packages/language/ug-CN.ts +19 -1
  164. package/packages/language/uk-UA.ts +19 -1
  165. package/packages/language/uz-UZ.ts +19 -1
  166. package/packages/language/vi-VN.ts +19 -1
  167. package/packages/language/zh-CHT.ts +19 -1
  168. package/packages/language/zh-CN.ts +18 -0
  169. package/packages/list/src/list.ts +1 -1
  170. package/packages/select/src/select.ts +146 -50
  171. package/packages/tree/src/tree.ts +947 -410
  172. package/packages/tree/src/util.ts +35 -0
  173. package/packages/tree-select/src/tree-select.ts +240 -19
  174. package/packages/ui/index.ts +18 -2
  175. package/packages/ui/src/dom.ts +10 -0
  176. package/styles/components/select.scss +19 -0
  177. package/styles/components/tree-select.scss +36 -1
  178. package/styles/components/tree.scss +34 -31
  179. package/types/components/button.d.ts +11 -1
  180. package/types/components/grid.d.ts +5 -0
  181. package/types/components/icon-picker.d.ts +11 -1
  182. package/types/components/input.d.ts +2 -2
  183. package/types/components/select.d.ts +28 -39
  184. package/types/components/tree-select.d.ts +73 -12
  185. package/types/components/tree.d.ts +125 -8
  186. /package/es/icon/{iconfont.1752151733538.ttf → iconfont.1752462949194.ttf} +0 -0
  187. /package/es/icon/{iconfont.1752151733538.woff → iconfont.1752462949194.woff} +0 -0
  188. /package/es/icon/{iconfont.1752151733538.woff2 → iconfont.1752462949194.woff2} +0 -0
  189. /package/es/{iconfont.1752151733538.ttf → iconfont.1752462949194.ttf} +0 -0
  190. /package/es/{iconfont.1752151733538.woff → iconfont.1752462949194.woff} +0 -0
  191. /package/es/{iconfont.1752151733538.woff2 → iconfont.1752462949194.woff2} +0 -0
  192. /package/lib/icon/style/{iconfont.1752151733538.ttf → iconfont.1752462949194.ttf} +0 -0
  193. /package/lib/icon/style/{iconfont.1752151733538.woff → iconfont.1752462949194.woff} +0 -0
  194. /package/lib/icon/style/{iconfont.1752151733538.woff2 → iconfont.1752462949194.woff2} +0 -0
  195. /package/lib/{iconfont.1752151733538.ttf → iconfont.1752462949194.ttf} +0 -0
  196. /package/lib/{iconfont.1752151733538.woff → iconfont.1752462949194.woff} +0 -0
  197. /package/lib/{iconfont.1752151733538.woff2 → iconfont.1752462949194.woff2} +0 -0
@@ -1,9 +1,11 @@
1
- import { ref, h, reactive, computed, watch, onUnmounted, nextTick } from 'vue';
1
+ import { ref, h, reactive, computed, watch, onUnmounted, nextTick, onMounted } from 'vue';
2
2
  import { defineVxeComponent } from '../../ui/src/comp';
3
- import { createEvent, getIcon, getConfig, useSize, renderEmptyElement } from '../../ui';
3
+ import { getI18n, createEvent, getIcon, getConfig, useSize, globalEvents, globalResize, renderEmptyElement } from '../../ui';
4
+ import { calcTreeLine } from './util';
5
+ import { errLog } from '../../ui/src/log';
4
6
  import XEUtils from 'xe-utils';
5
7
  import { getSlotVNs } from '../../ui/src/vn';
6
- import { toCssUnit } from '../../ui/src/dom';
8
+ import { toCssUnit, isScale, getPaddingTopBottomSize } from '../../ui/src/dom';
7
9
  import VxeLoadingComponent from '../../loading/src/loading';
8
10
  /**
9
11
  * 生成节点的唯一主键
@@ -15,7 +17,15 @@ export default defineVxeComponent({
15
17
  name: 'VxeTree',
16
18
  props: {
17
19
  data: Array,
20
+ autoResize: {
21
+ type: Boolean,
22
+ default: () => getConfig().tree.autoResize
23
+ },
18
24
  height: [String, Number],
25
+ maxHeight: {
26
+ type: [String, Number],
27
+ default: () => getConfig().tree.maxHeight
28
+ },
19
29
  minHeight: {
20
30
  type: [String, Number],
21
31
  default: () => getConfig().tree.minHeight
@@ -107,10 +117,13 @@ export default defineVxeComponent({
107
117
  type: String,
108
118
  default: () => getConfig().tree.iconLoaded
109
119
  },
120
+ filterValue: [String, Number],
121
+ filterConfig: Object,
110
122
  size: {
111
123
  type: String,
112
124
  default: () => getConfig().tree.size || getConfig().size
113
- }
125
+ },
126
+ virtualYConfig: Object
114
127
  },
115
128
  emits: [
116
129
  'update:modelValue',
@@ -122,15 +135,27 @@ export default defineVxeComponent({
122
135
  'radio-change',
123
136
  'checkbox-change',
124
137
  'load-success',
125
- 'load-error'
138
+ 'load-error',
139
+ 'scroll'
126
140
  ],
127
141
  setup(props, context) {
128
142
  const { emit, slots } = context;
129
143
  const xID = XEUtils.uniqueId();
130
144
  const { computeSize } = useSize(props);
131
145
  const refElem = ref();
146
+ const refHeaderWrapperElem = ref();
147
+ const refFooterWrapperElem = ref();
148
+ const refVirtualWrapper = ref();
149
+ const refVirtualBody = ref();
132
150
  const reactData = reactive({
151
+ parentHeight: 0,
152
+ customHeight: 0,
153
+ customMinHeight: 0,
154
+ customMaxHeight: 0,
133
155
  currentNode: null,
156
+ scrollYLoad: false,
157
+ bodyHeight: 0,
158
+ topSpaceHeight: 0,
134
159
  selectRadioKey: props.checkNodeKey,
135
160
  treeList: [],
136
161
  updateExpandedFlag: 1,
@@ -138,11 +163,26 @@ export default defineVxeComponent({
138
163
  });
139
164
  const internalData = {
140
165
  // initialized: false,
166
+ // lastFilterValue: '',
167
+ treeFullData: [],
168
+ afterTreeList: [],
169
+ afterVisibleList: [],
141
170
  nodeMaps: {},
142
171
  selectCheckboxMaps: {},
143
172
  indeterminateRowMaps: {},
144
173
  treeExpandedMaps: {},
145
- treeExpandLazyLoadedMaps: {}
174
+ treeExpandLazyLoadedMaps: {},
175
+ lastScrollLeft: 0,
176
+ lastScrollTop: 0,
177
+ scrollYStore: {
178
+ startIndex: 0,
179
+ endIndex: 0,
180
+ visibleSize: 0,
181
+ offsetSize: 0,
182
+ rowHeight: 0
183
+ },
184
+ lastScrollTime: 0
185
+ // hpTimeout: undefined
146
186
  };
147
187
  const refMaps = {
148
188
  refElem
@@ -169,6 +209,9 @@ export default defineVxeComponent({
169
209
  const computeHasChildField = computed(() => {
170
210
  return props.hasChildField || 'hasChild';
171
211
  });
212
+ const computeVirtualYOpts = computed(() => {
213
+ return Object.assign({}, getConfig().tree.virtualYConfig, props.virtualYConfig);
214
+ });
172
215
  const computeIsRowCurrent = computed(() => {
173
216
  const nodeOpts = computeNodeOpts.value;
174
217
  const { isCurrent } = nodeOpts;
@@ -198,17 +241,25 @@ export default defineVxeComponent({
198
241
  return Object.assign({}, getConfig().tree.loadingConfig, props.loadingConfig);
199
242
  });
200
243
  const computeTreeStyle = computed(() => {
201
- const { height, minHeight } = props;
244
+ const { customHeight, customMinHeight, customMaxHeight } = reactData;
202
245
  const stys = {};
203
- if (height) {
204
- stys.height = toCssUnit(height);
246
+ if (customHeight) {
247
+ stys.height = toCssUnit(customHeight);
248
+ }
249
+ if (customMinHeight) {
250
+ stys.minHeight = toCssUnit(customMinHeight);
205
251
  }
206
- if (minHeight) {
207
- stys.minHeight = toCssUnit(minHeight);
252
+ if (customMaxHeight) {
253
+ stys.maxHeight = toCssUnit(customMaxHeight);
208
254
  }
209
255
  return stys;
210
256
  });
257
+ const computeFilterOpts = computed(() => {
258
+ return Object.assign({}, getConfig().tree.filterConfig, props.filterConfig);
259
+ });
211
260
  const computeMaps = {
261
+ computeChildrenField,
262
+ computeMapChildrenField,
212
263
  computeRadioOpts,
213
264
  computeCheckboxOpts,
214
265
  computeNodeOpts
@@ -341,6 +392,39 @@ export default defineVxeComponent({
341
392
  const dispatchEvent = (type, params, evnt) => {
342
393
  emit(type, createEvent(evnt, { $tree: $xeTree }, params));
343
394
  };
395
+ const getParentElem = () => {
396
+ const el = refElem.value;
397
+ return el ? el.parentElement : null;
398
+ };
399
+ const calcTableHeight = (key) => {
400
+ const { parentHeight } = reactData;
401
+ const val = props[key];
402
+ let num = 0;
403
+ if (val) {
404
+ if (val === '100%' || val === 'auto') {
405
+ num = parentHeight;
406
+ }
407
+ else {
408
+ if (isScale(val)) {
409
+ num = Math.floor((XEUtils.toInteger(val) || 1) / 100 * parentHeight);
410
+ }
411
+ else {
412
+ num = XEUtils.toNumber(val);
413
+ }
414
+ num = Math.max(40, num);
415
+ }
416
+ }
417
+ return num;
418
+ };
419
+ const updateHeight = () => {
420
+ reactData.customHeight = calcTableHeight('height');
421
+ reactData.customMinHeight = calcTableHeight('minHeight');
422
+ reactData.customMaxHeight = calcTableHeight('maxHeight');
423
+ // 如果启用虚拟滚动,默认高度
424
+ if (reactData.scrollYLoad && !(reactData.customHeight || reactData.customMinHeight)) {
425
+ reactData.customHeight = 300;
426
+ }
427
+ };
344
428
  const createNode = (records) => {
345
429
  const valueField = computeValueField.value;
346
430
  return Promise.resolve(records.map(obj => {
@@ -353,352 +437,371 @@ export default defineVxeComponent({
353
437
  return item;
354
438
  }));
355
439
  };
356
- const treeMethods = {
357
- dispatchEvent,
358
- clearCurrentNode() {
359
- reactData.currentNode = null;
360
- return nextTick();
361
- },
362
- getCurrentNodeId() {
363
- const { currentNode } = reactData;
364
- if (currentNode) {
365
- return getNodeId(currentNode);
440
+ const cacheNodeMap = () => {
441
+ const { treeFullData } = internalData;
442
+ const valueField = computeValueField.value;
443
+ const childrenField = computeChildrenField.value;
444
+ const keyMaps = {};
445
+ XEUtils.eachTree(treeFullData, (item, index, items, path, parent, nodes) => {
446
+ let nodeid = getNodeId(item);
447
+ if (!nodeid) {
448
+ nodeid = getNodeUniqueId();
449
+ XEUtils.set(item, valueField, nodeid);
366
450
  }
367
- return null;
368
- },
369
- getCurrentNode() {
370
- const { currentNode } = reactData;
371
- const { nodeMaps } = internalData;
372
- if (currentNode) {
373
- const nodeItem = nodeMaps[getNodeId(currentNode)];
374
- if (nodeItem) {
375
- return nodeItem.item;
376
- }
451
+ keyMaps[nodeid] = {
452
+ item,
453
+ index,
454
+ items,
455
+ parent,
456
+ nodes,
457
+ level: nodes.length,
458
+ treeIndex: index,
459
+ lineCount: 0,
460
+ treeLoaded: false
461
+ };
462
+ }, { children: childrenField });
463
+ internalData.nodeMaps = keyMaps;
464
+ };
465
+ const updateAfterDataIndex = () => {
466
+ const { transform } = props;
467
+ const { afterTreeList, nodeMaps } = internalData;
468
+ const childrenField = computeChildrenField.value;
469
+ const mapChildrenField = computeMapChildrenField.value;
470
+ XEUtils.eachTree(afterTreeList, (item, index, items) => {
471
+ const nodeid = getNodeId(item);
472
+ const nodeItem = nodeMaps[nodeid];
473
+ if (nodeItem) {
474
+ nodeItem.items = items;
475
+ nodeItem.treeIndex = index;
377
476
  }
378
- return null;
379
- },
380
- setCurrentNodeId(nodeKey) {
381
- const { nodeMaps } = internalData;
382
- const nodeItem = nodeMaps[nodeKey];
383
- reactData.currentNode = nodeItem ? nodeItem.item : null;
384
- return nextTick();
385
- },
386
- setCurrentNode(node) {
387
- reactData.currentNode = node;
388
- return nextTick();
389
- },
390
- clearRadioNode() {
391
- reactData.selectRadioKey = null;
392
- return nextTick();
393
- },
394
- getRadioNodeId() {
395
- return reactData.selectRadioKey || null;
396
- },
397
- getRadioNode() {
398
- const { selectRadioKey } = reactData;
399
- const { nodeMaps } = internalData;
400
- if (selectRadioKey) {
401
- const nodeItem = nodeMaps[selectRadioKey];
402
- if (nodeItem) {
403
- return nodeItem.item;
404
- }
477
+ else {
478
+ const rest = {
479
+ item,
480
+ index,
481
+ items,
482
+ parent,
483
+ nodes: [],
484
+ level: 0,
485
+ treeIndex: index,
486
+ lineCount: 0,
487
+ treeLoaded: false
488
+ };
489
+ nodeMaps[nodeid] = rest;
405
490
  }
406
- return null;
407
- },
408
- setRadioNodeId(nodeKey) {
409
- reactData.selectRadioKey = nodeKey;
410
- return nextTick();
411
- },
412
- setRadioNode,
413
- setCheckboxNode,
414
- setCheckboxByNodeId,
415
- getCheckboxNodeIds() {
416
- const { selectCheckboxMaps } = internalData;
417
- return Object.keys(selectCheckboxMaps);
418
- },
419
- getCheckboxNodes() {
420
- const { nodeMaps, selectCheckboxMaps } = internalData;
421
- const list = [];
422
- XEUtils.each(selectCheckboxMaps, (item, nodeid) => {
423
- const nodeItem = nodeMaps[nodeid];
424
- if (nodeItem) {
425
- list.push(nodeItem.item);
491
+ }, { children: transform ? mapChildrenField : childrenField });
492
+ };
493
+ const updateAfterFullData = () => {
494
+ const { transform, filterValue } = props;
495
+ const { treeFullData, lastFilterValue } = internalData;
496
+ const titleField = computeTitleField.value;
497
+ const childrenField = computeChildrenField.value;
498
+ const mapChildrenField = computeMapChildrenField.value;
499
+ const filterOpts = computeFilterOpts.value;
500
+ const { autoExpandAll, beforeFilterMethod, filterMethod, afterFilterMethod } = filterOpts;
501
+ let fullList = treeFullData;
502
+ let treeList = fullList;
503
+ let filterStr = '';
504
+ if (filterValue || filterValue === 0) {
505
+ filterStr = `${filterValue}`;
506
+ const handleSearch = filterMethod
507
+ ? (item) => {
508
+ return filterMethod({
509
+ $tree: $xeTree,
510
+ node: item,
511
+ filterValue: filterStr
512
+ });
426
513
  }
427
- });
428
- return list;
429
- },
430
- clearCheckboxNode() {
431
- internalData.selectCheckboxMaps = {};
432
- reactData.updateCheckboxFlag++;
433
- return nextTick();
434
- },
435
- setAllCheckboxNode(checked) {
436
- const { transform } = props;
437
- const selectMaps = {};
438
- const childrenField = computeChildrenField.value;
439
- const mapChildrenField = computeMapChildrenField.value;
440
- if (checked) {
441
- XEUtils.eachTree(reactData.treeList, (node) => {
442
- const nodeid = getNodeId(node);
443
- selectMaps[nodeid] = true;
444
- }, { children: transform ? mapChildrenField : childrenField });
514
+ : (item) => {
515
+ return String(item[titleField]).toLowerCase().indexOf(filterStr) > -1;
516
+ };
517
+ const bafParams = { $tree: $xeTree, filterValue: filterStr };
518
+ if (beforeFilterMethod) {
519
+ beforeFilterMethod(bafParams);
445
520
  }
446
- internalData.selectCheckboxMaps = selectMaps;
447
- reactData.updateCheckboxFlag++;
448
- return nextTick();
449
- },
450
- clearExpandNode() {
451
- return treeMethods.clearAllExpandNode();
452
- },
453
- clearAllExpandNode() {
454
- const { nodeMaps } = internalData;
455
- XEUtils.each(nodeMaps, (nodeItem) => {
456
- nodeItem.treeLoaded = false;
457
- });
458
- internalData.treeExpandedMaps = {};
459
- reactData.updateExpandedFlag++;
460
- return nextTick();
461
- },
462
- setExpandByNodeId(nodeids, expanded) {
463
- const { treeExpandedMaps } = internalData;
464
- if (nodeids) {
465
- if (!XEUtils.isArray(nodeids)) {
466
- nodeids = [nodeids];
467
- }
468
- nodeids.forEach((nodeid) => {
469
- handleSetExpand(nodeid, expanded, treeExpandedMaps);
470
- });
471
- reactData.updateExpandedFlag++;
521
+ if (transform) {
522
+ treeList = XEUtils.searchTree(treeFullData, handleSearch, { children: childrenField, mapChildren: mapChildrenField, isEvery: true });
523
+ fullList = treeList;
472
524
  }
473
- return nextTick();
474
- },
475
- getExpandNodeIds() {
476
- const { treeExpandedMaps } = internalData;
477
- return XEUtils.keys(treeExpandedMaps);
478
- },
479
- getExpandNodes() {
480
- const { nodeMaps, treeExpandedMaps } = internalData;
481
- const list = [];
482
- XEUtils.each(treeExpandedMaps, (item, nodeid) => {
483
- const nodeItem = nodeMaps[nodeid];
484
- if (nodeItem) {
485
- list.push(nodeItem.item);
525
+ else {
526
+ fullList = treeFullData.filter(handleSearch);
527
+ }
528
+ internalData.lastFilterValue = filterStr;
529
+ nextTick(() => {
530
+ // 筛选时自动展开
531
+ if (autoExpandAll) {
532
+ $xeTree.setAllExpandNode(true).then(() => {
533
+ if (afterFilterMethod) {
534
+ afterFilterMethod(bafParams);
535
+ }
536
+ });
537
+ }
538
+ else {
539
+ if (afterFilterMethod) {
540
+ afterFilterMethod(bafParams);
541
+ }
486
542
  }
487
543
  });
488
- return list;
489
- },
490
- setExpandNode(nodes, expanded) {
491
- const { treeExpandedMaps } = internalData;
492
- if (nodes) {
493
- if (!XEUtils.isArray(nodes)) {
494
- nodes = [nodes];
544
+ }
545
+ else {
546
+ if (transform) {
547
+ treeList = XEUtils.searchTree(treeFullData, () => true, { children: childrenField, mapChildren: mapChildrenField, isEvery: true });
548
+ fullList = treeList;
549
+ if (lastFilterValue) {
550
+ const bafParams = { $tree: $xeTree, filterValue: filterStr };
551
+ if (beforeFilterMethod) {
552
+ beforeFilterMethod(bafParams);
553
+ }
554
+ // 取消筛选时自动收起
555
+ nextTick(() => {
556
+ if (autoExpandAll) {
557
+ $xeTree.clearAllExpandNode().then(() => {
558
+ if (afterFilterMethod) {
559
+ afterFilterMethod(bafParams);
560
+ }
561
+ });
562
+ }
563
+ else {
564
+ if (afterFilterMethod) {
565
+ afterFilterMethod(bafParams);
566
+ }
567
+ }
568
+ });
495
569
  }
496
- nodes.forEach((node) => {
497
- const nodeid = getNodeId(node);
498
- handleSetExpand(nodeid, expanded, treeExpandedMaps);
499
- });
500
- reactData.updateExpandedFlag++;
501
570
  }
502
- return nextTick();
503
- },
504
- toggleExpandByNodeId(nodeids) {
505
- const { treeExpandedMaps } = internalData;
506
- if (nodeids) {
507
- if (!XEUtils.isArray(nodeids)) {
508
- nodeids = [nodeids];
571
+ internalData.lastFilterValue = '';
572
+ }
573
+ internalData.afterVisibleList = fullList;
574
+ internalData.afterTreeList = treeList;
575
+ updateAfterDataIndex();
576
+ };
577
+ /**
578
+ * 如果为虚拟树、则将树结构拍平
579
+ */
580
+ const handleTreeToList = () => {
581
+ const { transform } = props;
582
+ const { afterTreeList, treeExpandedMaps } = internalData;
583
+ const mapChildrenField = computeMapChildrenField.value;
584
+ const expandMaps = {};
585
+ if (transform) {
586
+ const fullData = [];
587
+ XEUtils.eachTree(afterTreeList, (item, index, items, path, parentRow) => {
588
+ const nodeid = getNodeId(item);
589
+ const parentNodeid = getNodeId(parentRow);
590
+ if (!parentRow || (expandMaps[parentNodeid] && treeExpandedMaps[parentNodeid])) {
591
+ expandMaps[nodeid] = 1;
592
+ fullData.push(item);
509
593
  }
510
- nodeids.forEach((nodeid) => {
511
- handleSetExpand(nodeid, !treeExpandedMaps[nodeid], treeExpandedMaps);
512
- });
513
- reactData.updateExpandedFlag++;
594
+ }, { children: mapChildrenField });
595
+ updateScrollYStatus(fullData);
596
+ internalData.afterVisibleList = fullData;
597
+ return fullData;
598
+ }
599
+ return internalData.afterVisibleList;
600
+ };
601
+ const handleData = (force) => {
602
+ const { scrollYLoad } = reactData;
603
+ const { scrollYStore } = internalData;
604
+ let fullList = internalData.afterVisibleList;
605
+ if (force) {
606
+ // 更新数据,处理筛选和排序
607
+ updateAfterFullData();
608
+ // 如果为虚拟树,将树结构拍平
609
+ fullList = handleTreeToList();
610
+ }
611
+ const treeList = scrollYLoad ? fullList.slice(scrollYStore.startIndex, scrollYStore.endIndex) : fullList.slice(0);
612
+ reactData.treeList = treeList;
613
+ };
614
+ const triggerSearchEvent = XEUtils.debounce(() => handleData(true), 350, { trailing: true });
615
+ const loadData = (list) => {
616
+ const { expandAll, transform } = props;
617
+ const { initialized, scrollYStore } = internalData;
618
+ const keyField = computeKeyField.value;
619
+ const parentField = computeParentField.value;
620
+ const childrenField = computeChildrenField.value;
621
+ const fullData = transform ? XEUtils.toArrayTree(list, { key: keyField, parentKey: parentField, mapChildren: childrenField }) : list ? list.slice(0) : [];
622
+ internalData.treeFullData = fullData;
623
+ Object.assign(scrollYStore, {
624
+ startIndex: 0,
625
+ endIndex: 1,
626
+ visibleSize: 0
627
+ });
628
+ const sYLoad = updateScrollYStatus(fullData);
629
+ cacheNodeMap();
630
+ handleData(true);
631
+ if (sYLoad) {
632
+ if (!(props.height || props.maxHeight)) {
633
+ errLog('vxe.error.reqProp', ['height | max-height | virtual-y-config.enabled=false']);
514
634
  }
515
- return nextTick();
516
- },
517
- toggleExpandNode(nodes) {
518
- const { treeExpandedMaps } = internalData;
519
- if (nodes) {
520
- if (!XEUtils.isArray(nodes)) {
521
- nodes = [nodes];
635
+ }
636
+ return computeScrollLoad().then(() => {
637
+ if (!initialized) {
638
+ if (list && list.length) {
639
+ internalData.initialized = true;
640
+ if (expandAll) {
641
+ $xeTree.setAllExpandNode(true);
642
+ }
643
+ $xeTree.setCheckboxByNodeId(props.checkNodeKeys || [], true);
522
644
  }
523
- nodes.forEach((node) => {
524
- const nodeid = getNodeId(node);
525
- handleSetExpand(nodeid, !treeExpandedMaps[nodeid], treeExpandedMaps);
526
- });
527
- reactData.updateExpandedFlag++;
528
645
  }
529
- return nextTick();
530
- },
531
- setAllExpandNode(expanded) {
532
- const { transform } = props;
533
- const { treeExpandedMaps } = internalData;
534
- const childrenField = computeChildrenField.value;
535
- const mapChildrenField = computeMapChildrenField.value;
536
- if (expanded) {
537
- XEUtils.eachTree(reactData.treeList, (node) => {
538
- const childList = XEUtils.get(node, childrenField);
539
- const hasChild = childList && childList.length;
540
- if (hasChild) {
541
- const nodeid = getNodeId(node);
542
- treeExpandedMaps[nodeid] = true;
543
- }
544
- }, { children: transform ? mapChildrenField : childrenField });
646
+ updateHeight();
647
+ refreshScroll();
648
+ });
649
+ };
650
+ const updateScrollYStatus = (fullData) => {
651
+ const { transform } = props;
652
+ const virtualYOpts = computeVirtualYOpts.value;
653
+ const allList = fullData || internalData.treeFullData;
654
+ // 如果gt为0,则总是启用
655
+ const scrollYLoad = !!transform && !!virtualYOpts.enabled && virtualYOpts.gt > -1 && (virtualYOpts.gt === 0 || virtualYOpts.gt < allList.length);
656
+ reactData.scrollYLoad = scrollYLoad;
657
+ return scrollYLoad;
658
+ };
659
+ const updateYSpace = () => {
660
+ const { scrollYLoad } = reactData;
661
+ const { scrollYStore, afterVisibleList } = internalData;
662
+ reactData.bodyHeight = scrollYLoad ? afterVisibleList.length * scrollYStore.rowHeight : 0;
663
+ reactData.topSpaceHeight = scrollYLoad ? Math.max(scrollYStore.startIndex * scrollYStore.rowHeight, 0) : 0;
664
+ };
665
+ const updateYData = () => {
666
+ handleData();
667
+ updateYSpace();
668
+ };
669
+ const computeScrollLoad = () => {
670
+ return nextTick().then(() => {
671
+ const { scrollYLoad } = reactData;
672
+ const { scrollYStore } = internalData;
673
+ const virtualBodyElem = refVirtualBody.value;
674
+ const virtualYOpts = computeVirtualYOpts.value;
675
+ let rowHeight = 0;
676
+ let firstItemElem;
677
+ if (virtualBodyElem) {
678
+ if (!firstItemElem) {
679
+ firstItemElem = virtualBodyElem.children[0];
680
+ }
545
681
  }
546
- else {
547
- internalData.treeExpandedMaps = {};
682
+ if (firstItemElem) {
683
+ rowHeight = firstItemElem.offsetHeight;
548
684
  }
549
- reactData.updateExpandedFlag++;
550
- return nextTick();
551
- },
552
- reloadExpandNode(node) {
553
- const { lazy } = props;
554
- if (lazy) {
555
- treeMethods.clearExpandLoaded(node);
556
- return handleAsyncTreeExpandChilds(node);
685
+ rowHeight = Math.max(20, rowHeight);
686
+ scrollYStore.rowHeight = rowHeight;
687
+ // 计算 Y 逻辑
688
+ if (scrollYLoad) {
689
+ const scrollBodyElem = refVirtualWrapper.value;
690
+ const visibleYSize = Math.max(8, scrollBodyElem ? Math.ceil(scrollBodyElem.clientHeight / rowHeight) : 0);
691
+ const offsetYSize = Math.max(0, Math.min(2, XEUtils.toNumber(virtualYOpts.oSize)));
692
+ scrollYStore.offsetSize = offsetYSize;
693
+ scrollYStore.visibleSize = visibleYSize;
694
+ scrollYStore.endIndex = Math.max(scrollYStore.startIndex, visibleYSize + offsetYSize, scrollYStore.endIndex);
695
+ updateYData();
557
696
  }
558
- return nextTick();
559
- },
560
- clearExpandLoaded(node) {
561
- const { lazy } = props;
562
- const { nodeMaps } = internalData;
563
- if (lazy) {
564
- const nodeItem = nodeMaps[getNodeId(node)];
565
- if (nodeItem) {
566
- nodeItem.treeLoaded = false;
567
- }
697
+ else {
698
+ updateYSpace();
568
699
  }
569
- return nextTick();
570
- },
571
- /**
572
- * 用于树结构,给行数据加载子节点
573
- */
574
- loadChildrenNode(node, childRecords) {
575
- const { lazy, transform } = props;
576
- const { nodeMaps } = internalData;
577
- if (!lazy) {
578
- return Promise.resolve([]);
700
+ });
701
+ };
702
+ /**
703
+ * 如果有滚动条,则滚动到对应的位置
704
+ * @param {Number} scrollLeft 左距离
705
+ * @param {Number} scrollTop 上距离
706
+ */
707
+ const scrollTo = (scrollLeft, scrollTop) => {
708
+ const scrollBodyElem = refVirtualWrapper.value;
709
+ if (scrollBodyElem) {
710
+ if (XEUtils.isNumber(scrollLeft)) {
711
+ scrollBodyElem.scrollLeft = scrollLeft;
579
712
  }
580
- const childrenField = computeChildrenField.value;
581
- const parentNodeItem = nodeMaps[getNodeId(node)];
582
- const parentLevel = parentNodeItem ? parentNodeItem.level : 0;
583
- const parentNodes = parentNodeItem ? parentNodeItem.nodes : [];
584
- return createNode(childRecords).then((nodeList) => {
585
- XEUtils.eachTree(nodeList, (childRow, index, items, path, parent, nodes) => {
586
- const itemNodeId = getNodeId(childRow);
587
- nodeMaps[itemNodeId] = {
588
- item: node,
589
- itemIndex: -1,
590
- items,
591
- parent: parent || parentNodeItem.item,
592
- nodes: parentNodes.concat(nodes),
593
- level: parentLevel + nodes.length,
594
- lineCount: 0,
595
- treeLoaded: false
596
- };
597
- }, { children: childrenField });
598
- node[childrenField] = nodeList;
599
- if (transform) {
600
- node[childrenField] = nodeList;
601
- }
602
- updateNodeLine(node);
603
- return nodeList;
604
- });
605
- },
606
- isExpandByNode,
607
- isCheckedByRadioNodeId,
608
- isCheckedByRadioNode,
609
- isCheckedByCheckboxNodeId,
610
- isIndeterminateByCheckboxNode,
611
- isCheckedByCheckboxNode,
612
- getCheckboxIndeterminateNodes() {
613
- const { nodeMaps, indeterminateRowMaps } = internalData;
614
- const list = [];
615
- XEUtils.each(indeterminateRowMaps, (item, nodeid) => {
616
- const nodeItem = nodeMaps[nodeid];
617
- if (nodeItem) {
618
- list.push(nodeItem.item);
619
- }
713
+ if (XEUtils.isNumber(scrollTop)) {
714
+ scrollBodyElem.scrollTop = scrollTop;
715
+ }
716
+ }
717
+ if (reactData.scrollYLoad) {
718
+ return new Promise(resolve => {
719
+ setTimeout(() => {
720
+ nextTick(() => {
721
+ resolve();
722
+ });
723
+ }, 50);
620
724
  });
621
- return list;
622
725
  }
726
+ return nextTick();
623
727
  };
624
- const cacheNodeMap = () => {
625
- const { transform } = props;
626
- const { treeList } = reactData;
627
- const valueField = computeValueField.value;
628
- const childrenField = computeChildrenField.value;
629
- const mapChildrenField = computeMapChildrenField.value;
630
- const keyMaps = {};
631
- XEUtils.eachTree(treeList, (item, itemIndex, items, path, parent, nodes) => {
632
- let nodeid = getNodeId(item);
633
- if (!nodeid) {
634
- nodeid = getNodeUniqueId();
635
- XEUtils.set(item, valueField, nodeid);
728
+ /**
729
+ * 刷新滚动条
730
+ */
731
+ const refreshScroll = () => {
732
+ const { lastScrollLeft, lastScrollTop } = internalData;
733
+ return clearScroll().then(() => {
734
+ if (lastScrollLeft || lastScrollTop) {
735
+ internalData.lastScrollLeft = 0;
736
+ internalData.lastScrollTop = 0;
737
+ return scrollTo(lastScrollLeft, lastScrollTop);
636
738
  }
637
- keyMaps[nodeid] = {
638
- item,
639
- itemIndex,
640
- items,
641
- parent,
642
- nodes,
643
- level: nodes.length,
644
- lineCount: 0,
645
- treeLoaded: false
646
- };
647
- }, { children: transform ? mapChildrenField : childrenField });
648
- internalData.nodeMaps = keyMaps;
739
+ });
649
740
  };
650
- const loadTreeData = (list) => {
651
- const { expandAll, transform } = props;
652
- const { initialized } = internalData;
653
- const keyField = computeKeyField.value;
654
- const parentField = computeParentField.value;
655
- const mapChildrenField = computeMapChildrenField.value;
656
- if (transform) {
657
- reactData.treeList = XEUtils.toArrayTree(list, { key: keyField, parentKey: parentField, mapChildren: mapChildrenField });
658
- }
659
- else {
660
- reactData.treeList = list ? list.slice(0) : [];
741
+ /**
742
+ * 重新计算列表
743
+ */
744
+ const recalculate = () => {
745
+ const { scrollYStore } = internalData;
746
+ const { rowHeight } = scrollYStore;
747
+ const el = refElem.value;
748
+ if (el && el.clientWidth && el.clientHeight) {
749
+ const parentEl = getParentElem();
750
+ const headerWrapperEl = refHeaderWrapperElem.value;
751
+ const footerWrapperEl = refFooterWrapperElem.value;
752
+ const headHeight = headerWrapperEl ? headerWrapperEl.clientHeight : 0;
753
+ const footHeight = footerWrapperEl ? footerWrapperEl.clientHeight : 0;
754
+ if (parentEl) {
755
+ const parentPaddingSize = getPaddingTopBottomSize(parentEl);
756
+ reactData.parentHeight = Math.max(headHeight + footHeight + rowHeight, parentEl.clientHeight - parentPaddingSize - headHeight - footHeight);
757
+ }
758
+ updateHeight();
759
+ return computeScrollLoad().then(() => {
760
+ updateHeight();
761
+ updateYSpace();
762
+ });
661
763
  }
662
- cacheNodeMap();
663
- if (!initialized) {
664
- if (list && list.length) {
665
- internalData.initialized = true;
666
- if (expandAll) {
667
- $xeTree.setAllExpandNode(true);
668
- }
669
- $xeTree.setCheckboxByNodeId(props.checkNodeKeys || [], true);
764
+ return nextTick();
765
+ };
766
+ const loadYData = (evnt) => {
767
+ const { scrollYStore } = internalData;
768
+ const { startIndex, endIndex, visibleSize, offsetSize, rowHeight } = scrollYStore;
769
+ const scrollBodyElem = evnt.target;
770
+ const scrollTop = scrollBodyElem.scrollTop;
771
+ const toVisibleIndex = Math.floor(scrollTop / rowHeight);
772
+ const offsetStartIndex = Math.max(0, toVisibleIndex - 1 - offsetSize);
773
+ const offsetEndIndex = toVisibleIndex + visibleSize + offsetSize;
774
+ if (toVisibleIndex <= startIndex || toVisibleIndex >= endIndex - visibleSize - 1) {
775
+ if (startIndex !== offsetStartIndex || endIndex !== offsetEndIndex) {
776
+ scrollYStore.startIndex = offsetStartIndex;
777
+ scrollYStore.endIndex = offsetEndIndex;
778
+ updateYData();
670
779
  }
671
780
  }
672
781
  };
673
- const handleCountLine = (item, isRoot, nodeItem) => {
674
- const { treeExpandedMaps } = internalData;
675
- const childrenField = computeChildrenField.value;
676
- const nodeid = getNodeId(item);
677
- nodeItem.lineCount++;
678
- if (treeExpandedMaps[nodeid]) {
679
- XEUtils.arrayEach(item[childrenField], (childItem, childIndex, childList) => {
680
- if (!isRoot || childIndex < childList.length - 1) {
681
- handleCountLine(childItem, false, nodeItem);
682
- }
683
- });
782
+ const scrollEvent = (evnt) => {
783
+ const scrollBodyElem = evnt.target;
784
+ const scrollTop = scrollBodyElem.scrollTop;
785
+ const scrollLeft = scrollBodyElem.scrollLeft;
786
+ const isX = scrollLeft !== internalData.lastScrollLeft;
787
+ const isY = scrollTop !== internalData.lastScrollTop;
788
+ internalData.lastScrollTop = scrollTop;
789
+ internalData.lastScrollLeft = scrollLeft;
790
+ if (reactData.scrollYLoad) {
791
+ loadYData(evnt);
684
792
  }
793
+ internalData.lastScrollTime = Date.now();
794
+ dispatchEvent('scroll', { scrollLeft, scrollTop, isX, isY }, evnt);
685
795
  };
686
- const updateNodeLine = (node) => {
687
- const { nodeMaps } = internalData;
688
- if (node) {
689
- const nodeid = getNodeId(node);
690
- const nodeItem = nodeMaps[nodeid];
691
- if (nodeItem) {
692
- XEUtils.lastArrayEach(nodeItem.nodes, childItem => {
693
- const nodeid = getNodeId(childItem);
694
- const nodeItem = nodeMaps[nodeid];
695
- if (nodeItem) {
696
- nodeItem.lineCount = 0;
697
- handleCountLine(childItem, true, nodeItem);
698
- }
699
- });
700
- }
796
+ const clearScroll = () => {
797
+ const scrollBodyElem = refVirtualWrapper.value;
798
+ if (scrollBodyElem) {
799
+ scrollBodyElem.scrollTop = 0;
800
+ scrollBodyElem.scrollLeft = 0;
701
801
  }
802
+ internalData.lastScrollTop = 0;
803
+ internalData.lastScrollLeft = 0;
804
+ return nextTick();
702
805
  };
703
806
  const handleNodeClickEvent = (evnt, node) => {
704
807
  const { showRadio, showCheckbox, trigger } = props;
@@ -763,13 +866,11 @@ export default defineVxeComponent({
763
866
  if (!checkStrictly && $xeTree.isCheckedByCheckboxNodeId(nodeid)) {
764
867
  handleCheckedCheckboxNode(childRows, true);
765
868
  }
766
- updateNodeLine(node);
767
869
  dispatchEvent('load-success', { node, data: childRecords }, new Event('load-success'));
768
870
  return nextTick();
769
871
  });
770
872
  }
771
873
  else {
772
- updateNodeLine(node);
773
874
  dispatchEvent('load-success', { node, data: childRecords }, new Event('load-success'));
774
875
  }
775
876
  }).catch((e) => {
@@ -778,10 +879,11 @@ export default defineVxeComponent({
778
879
  if (treeExpandLazyLoadedMaps[nodeid]) {
779
880
  treeExpandLazyLoadedMaps[nodeid] = false;
780
881
  }
781
- updateNodeLine(node);
782
882
  dispatchEvent('load-error', { node, data: e }, new Event('load-error'));
783
883
  }).finally(() => {
784
- return nextTick();
884
+ handleTreeToList();
885
+ handleData();
886
+ return recalculate();
785
887
  });
786
888
  }
787
889
  else {
@@ -847,8 +949,9 @@ export default defineVxeComponent({
847
949
  });
848
950
  }
849
951
  reactData.updateExpandedFlag++;
850
- expandNodes.forEach(updateNodeLine);
851
- return Promise.all(result);
952
+ handleTreeToList();
953
+ handleData();
954
+ return Promise.all(result).then(() => recalculate());
852
955
  };
853
956
  const toggleExpandEvent = (evnt, node) => {
854
957
  const { lazy } = props;
@@ -862,8 +965,7 @@ export default defineVxeComponent({
862
965
  };
863
966
  const updateCheckboxStatus = () => {
864
967
  const { transform } = props;
865
- const { treeList } = reactData;
866
- const { selectCheckboxMaps, indeterminateRowMaps } = internalData;
968
+ const { selectCheckboxMaps, indeterminateRowMaps, afterTreeList } = internalData;
867
969
  const childrenField = computeChildrenField.value;
868
970
  const mapChildrenField = computeMapChildrenField.value;
869
971
  const checkboxOpts = computeCheckboxOpts.value;
@@ -871,7 +973,7 @@ export default defineVxeComponent({
871
973
  if (!checkStrictly) {
872
974
  const childRowMaps = {};
873
975
  const childRowList = [];
874
- XEUtils.eachTree(treeList, (node) => {
976
+ XEUtils.eachTree(afterTreeList, (node) => {
875
977
  const nodeid = getNodeId(node);
876
978
  const childList = node[childrenField];
877
979
  if (childList && childList.length && !childRowMaps[nodeid]) {
@@ -885,12 +987,13 @@ export default defineVxeComponent({
885
987
  const childList = vals[2];
886
988
  let sLen = 0; // 已选
887
989
  let hLen = 0; // 半选
888
- let vLen = 0; // 有效行
990
+ let vLen = 0; // 有效子行
991
+ const cLen = childList.length; // 子行
889
992
  childList.forEach(checkMethod
890
993
  ? (item) => {
891
994
  const childNodeid = getNodeId(item);
892
995
  const isSelect = selectCheckboxMaps[childNodeid];
893
- if (checkMethod({ node: item })) {
996
+ if (checkMethod({ $tree: $xeTree, node: item })) {
894
997
  if (isSelect) {
895
998
  sLen++;
896
999
  }
@@ -919,8 +1022,29 @@ export default defineVxeComponent({
919
1022
  }
920
1023
  vLen++;
921
1024
  });
922
- const isSelected = sLen >= vLen;
923
- const halfSelect = !isSelected && (sLen >= 1 || hLen >= 1);
1025
+ let isSelected = false;
1026
+ if (cLen > 0) {
1027
+ if (vLen > 0) {
1028
+ isSelected = (sLen > 0 || hLen > 0) && sLen >= vLen;
1029
+ }
1030
+ else {
1031
+ // 如果存在子项禁用
1032
+ if ((sLen > 0 && sLen >= vLen)) {
1033
+ isSelected = true;
1034
+ }
1035
+ else if (selectCheckboxMaps[nodeid]) {
1036
+ isSelected = true;
1037
+ }
1038
+ else {
1039
+ isSelected = false;
1040
+ }
1041
+ }
1042
+ }
1043
+ else {
1044
+ // 如果无子项
1045
+ isSelected = selectCheckboxMaps[nodeid];
1046
+ }
1047
+ const halfSelect = !isSelected && (sLen > 0 || hLen > 0);
924
1048
  if (isSelected) {
925
1049
  selectCheckboxMaps[nodeid] = node;
926
1050
  if (indeterminateRowMaps[nodeid]) {
@@ -955,7 +1079,7 @@ export default defineVxeComponent({
955
1079
  const { checkStrictly, checkMethod } = checkboxOpts;
956
1080
  let isDisabled = !!checkMethod;
957
1081
  if (checkMethod) {
958
- isDisabled = !checkMethod({ node });
1082
+ isDisabled = !checkMethod({ $tree: $xeTree, node });
959
1083
  }
960
1084
  if (isDisabled) {
961
1085
  return;
@@ -970,7 +1094,7 @@ export default defineVxeComponent({
970
1094
  selectCheckboxMaps[nodeid] = node;
971
1095
  }
972
1096
  if (!checkStrictly) {
973
- XEUtils.eachTree(XEUtils.get(node, childrenField), (childNode) => {
1097
+ XEUtils.eachTree(XEUtils.get(node, transform ? mapChildrenField : childrenField), (childNode) => {
974
1098
  const childNodeid = getNodeId(childNode);
975
1099
  if (isChecked) {
976
1100
  if (!selectCheckboxMaps[childNodeid]) {
@@ -1025,7 +1149,7 @@ export default defineVxeComponent({
1025
1149
  const { checkMethod } = radioOpts;
1026
1150
  let isDisabled = !!checkMethod;
1027
1151
  if (checkMethod) {
1028
- isDisabled = !checkMethod({ node });
1152
+ isDisabled = !checkMethod({ $tree: $xeTree, node });
1029
1153
  }
1030
1154
  if (isDisabled) {
1031
1155
  return;
@@ -1036,17 +1160,325 @@ export default defineVxeComponent({
1036
1160
  emitRadioMode(value);
1037
1161
  dispatchEvent('radio-change', { node, value, checked: isChecked }, evnt);
1038
1162
  };
1163
+ const handleGlobalResizeEvent = () => {
1164
+ const el = refElem.value;
1165
+ if (!el || !el.clientWidth) {
1166
+ return;
1167
+ }
1168
+ recalculate();
1169
+ };
1170
+ const treeMethods = {
1171
+ dispatchEvent,
1172
+ getNodeId,
1173
+ loadData(data) {
1174
+ return loadData(data || []);
1175
+ },
1176
+ reloadData(data) {
1177
+ return loadData(data || []);
1178
+ },
1179
+ clearCurrentNode() {
1180
+ reactData.currentNode = null;
1181
+ return nextTick();
1182
+ },
1183
+ getCurrentNodeId() {
1184
+ const { currentNode } = reactData;
1185
+ if (currentNode) {
1186
+ return getNodeId(currentNode);
1187
+ }
1188
+ return null;
1189
+ },
1190
+ getCurrentNode() {
1191
+ const { currentNode } = reactData;
1192
+ const { nodeMaps } = internalData;
1193
+ if (currentNode) {
1194
+ const nodeItem = nodeMaps[getNodeId(currentNode)];
1195
+ if (nodeItem) {
1196
+ return nodeItem.item;
1197
+ }
1198
+ }
1199
+ return null;
1200
+ },
1201
+ setCurrentNodeId(nodeKey) {
1202
+ const { nodeMaps } = internalData;
1203
+ const nodeItem = nodeMaps[nodeKey];
1204
+ reactData.currentNode = nodeItem ? nodeItem.item : null;
1205
+ return nextTick();
1206
+ },
1207
+ setCurrentNode(node) {
1208
+ reactData.currentNode = node;
1209
+ return nextTick();
1210
+ },
1211
+ clearRadioNode() {
1212
+ reactData.selectRadioKey = null;
1213
+ return nextTick();
1214
+ },
1215
+ getRadioNodeId() {
1216
+ return reactData.selectRadioKey || null;
1217
+ },
1218
+ getRadioNode() {
1219
+ const { selectRadioKey } = reactData;
1220
+ const { nodeMaps } = internalData;
1221
+ if (selectRadioKey) {
1222
+ const nodeItem = nodeMaps[selectRadioKey];
1223
+ if (nodeItem) {
1224
+ return nodeItem.item;
1225
+ }
1226
+ }
1227
+ return null;
1228
+ },
1229
+ setRadioNodeId(nodeKey) {
1230
+ reactData.selectRadioKey = nodeKey;
1231
+ return nextTick();
1232
+ },
1233
+ setRadioNode,
1234
+ setCheckboxNode,
1235
+ setCheckboxByNodeId,
1236
+ getCheckboxNodeIds() {
1237
+ const { selectCheckboxMaps } = internalData;
1238
+ return Object.keys(selectCheckboxMaps);
1239
+ },
1240
+ getCheckboxNodes() {
1241
+ const { nodeMaps, selectCheckboxMaps } = internalData;
1242
+ const list = [];
1243
+ XEUtils.each(selectCheckboxMaps, (item, nodeid) => {
1244
+ const nodeItem = nodeMaps[nodeid];
1245
+ if (nodeItem) {
1246
+ list.push(nodeItem.item);
1247
+ }
1248
+ });
1249
+ return list;
1250
+ },
1251
+ clearCheckboxNode() {
1252
+ internalData.selectCheckboxMaps = {};
1253
+ reactData.updateCheckboxFlag++;
1254
+ return nextTick().then(() => {
1255
+ return { checkNodeKeys: [] };
1256
+ });
1257
+ },
1258
+ setAllCheckboxNode(checked) {
1259
+ const { transform } = props;
1260
+ const selectMaps = {};
1261
+ const childrenField = computeChildrenField.value;
1262
+ const mapChildrenField = computeMapChildrenField.value;
1263
+ const checkKeys = [];
1264
+ if (checked) {
1265
+ XEUtils.eachTree(internalData.afterTreeList, (node) => {
1266
+ const nodeid = getNodeId(node);
1267
+ checkKeys.push(nodeid);
1268
+ selectMaps[nodeid] = true;
1269
+ }, { children: transform ? mapChildrenField : childrenField });
1270
+ }
1271
+ internalData.selectCheckboxMaps = selectMaps;
1272
+ reactData.updateCheckboxFlag++;
1273
+ return nextTick().then(() => {
1274
+ return { checkNodeKeys: checkKeys };
1275
+ });
1276
+ },
1277
+ clearExpandNode() {
1278
+ return treeMethods.clearAllExpandNode();
1279
+ },
1280
+ clearAllExpandNode() {
1281
+ const { nodeMaps, scrollYStore } = internalData;
1282
+ XEUtils.each(nodeMaps, (nodeItem) => {
1283
+ nodeItem.treeLoaded = false;
1284
+ });
1285
+ internalData.treeExpandedMaps = {};
1286
+ reactData.updateExpandedFlag++;
1287
+ reactData.topSpaceHeight = 0;
1288
+ scrollYStore.startIndex = 0;
1289
+ scrollYStore.endIndex = 1;
1290
+ handleTreeToList();
1291
+ handleData();
1292
+ return recalculate();
1293
+ },
1294
+ setExpandByNodeId(nodeids, expanded) {
1295
+ const { treeExpandedMaps } = internalData;
1296
+ if (nodeids) {
1297
+ if (!XEUtils.isArray(nodeids)) {
1298
+ nodeids = [nodeids];
1299
+ }
1300
+ nodeids.forEach((nodeid) => {
1301
+ handleSetExpand(nodeid, expanded, treeExpandedMaps);
1302
+ });
1303
+ reactData.updateExpandedFlag++;
1304
+ }
1305
+ handleTreeToList();
1306
+ handleData();
1307
+ return recalculate();
1308
+ },
1309
+ getExpandNodeIds() {
1310
+ const { treeExpandedMaps } = internalData;
1311
+ return XEUtils.keys(treeExpandedMaps);
1312
+ },
1313
+ getExpandNodes() {
1314
+ const { nodeMaps, treeExpandedMaps } = internalData;
1315
+ const list = [];
1316
+ XEUtils.each(treeExpandedMaps, (item, nodeid) => {
1317
+ const nodeItem = nodeMaps[nodeid];
1318
+ if (nodeItem) {
1319
+ list.push(nodeItem.item);
1320
+ }
1321
+ });
1322
+ return list;
1323
+ },
1324
+ setExpandNode(nodes, expanded) {
1325
+ const { treeExpandedMaps } = internalData;
1326
+ if (nodes) {
1327
+ if (!XEUtils.isArray(nodes)) {
1328
+ nodes = [nodes];
1329
+ }
1330
+ nodes.forEach((node) => {
1331
+ const nodeid = getNodeId(node);
1332
+ handleSetExpand(nodeid, expanded, treeExpandedMaps);
1333
+ });
1334
+ reactData.updateExpandedFlag++;
1335
+ }
1336
+ handleTreeToList();
1337
+ handleData();
1338
+ return recalculate();
1339
+ },
1340
+ toggleExpandByNodeId(nodeids) {
1341
+ const { treeExpandedMaps } = internalData;
1342
+ if (nodeids) {
1343
+ if (!XEUtils.isArray(nodeids)) {
1344
+ nodeids = [nodeids];
1345
+ }
1346
+ nodeids.forEach((nodeid) => {
1347
+ handleSetExpand(nodeid, !treeExpandedMaps[nodeid], treeExpandedMaps);
1348
+ });
1349
+ reactData.updateExpandedFlag++;
1350
+ }
1351
+ handleTreeToList();
1352
+ handleData();
1353
+ return recalculate();
1354
+ },
1355
+ toggleExpandNode(nodes) {
1356
+ const { treeExpandedMaps } = internalData;
1357
+ if (nodes) {
1358
+ if (!XEUtils.isArray(nodes)) {
1359
+ nodes = [nodes];
1360
+ }
1361
+ nodes.forEach((node) => {
1362
+ const nodeid = getNodeId(node);
1363
+ handleSetExpand(nodeid, !treeExpandedMaps[nodeid], treeExpandedMaps);
1364
+ });
1365
+ reactData.updateExpandedFlag++;
1366
+ }
1367
+ handleTreeToList();
1368
+ handleData();
1369
+ return recalculate();
1370
+ },
1371
+ setAllExpandNode(expanded) {
1372
+ const { transform } = props;
1373
+ const { treeExpandedMaps } = internalData;
1374
+ const childrenField = computeChildrenField.value;
1375
+ const mapChildrenField = computeMapChildrenField.value;
1376
+ if (expanded) {
1377
+ XEUtils.eachTree(internalData.afterTreeList, (node) => {
1378
+ const childList = XEUtils.get(node, childrenField);
1379
+ const hasChild = childList && childList.length;
1380
+ if (hasChild) {
1381
+ const nodeid = getNodeId(node);
1382
+ treeExpandedMaps[nodeid] = true;
1383
+ }
1384
+ }, { children: transform ? mapChildrenField : childrenField });
1385
+ }
1386
+ else {
1387
+ internalData.treeExpandedMaps = {};
1388
+ }
1389
+ reactData.updateExpandedFlag++;
1390
+ handleTreeToList();
1391
+ handleData();
1392
+ return recalculate();
1393
+ },
1394
+ reloadExpandNode(node) {
1395
+ const { lazy } = props;
1396
+ if (lazy) {
1397
+ treeMethods.clearExpandLoaded(node);
1398
+ return handleAsyncTreeExpandChilds(node);
1399
+ }
1400
+ return recalculate();
1401
+ },
1402
+ clearExpandLoaded(node) {
1403
+ const { lazy } = props;
1404
+ const { nodeMaps } = internalData;
1405
+ if (lazy) {
1406
+ const nodeItem = nodeMaps[getNodeId(node)];
1407
+ if (nodeItem) {
1408
+ nodeItem.treeLoaded = false;
1409
+ }
1410
+ }
1411
+ return recalculate();
1412
+ },
1413
+ /**
1414
+ * 用于树结构,给行数据加载子节点
1415
+ */
1416
+ loadChildrenNode(node, childRecords) {
1417
+ const { lazy, transform } = props;
1418
+ const { nodeMaps } = internalData;
1419
+ if (!lazy) {
1420
+ return Promise.resolve([]);
1421
+ }
1422
+ const childrenField = computeChildrenField.value;
1423
+ const mapChildrenField = computeMapChildrenField.value;
1424
+ const parentNodeItem = nodeMaps[getNodeId(node)];
1425
+ const parentLevel = parentNodeItem ? parentNodeItem.level : 0;
1426
+ const parentNodes = parentNodeItem ? parentNodeItem.nodes : [];
1427
+ return createNode(childRecords).then((nodeList) => {
1428
+ XEUtils.eachTree(nodeList, (childRow, index, items, path, parent, nodes) => {
1429
+ const itemNodeId = getNodeId(childRow);
1430
+ nodeMaps[itemNodeId] = {
1431
+ item: node,
1432
+ index: -1,
1433
+ items,
1434
+ parent: parent || parentNodeItem.item,
1435
+ nodes: parentNodes.concat(nodes),
1436
+ level: parentLevel + nodes.length,
1437
+ treeIndex: -1,
1438
+ lineCount: 0,
1439
+ treeLoaded: false
1440
+ };
1441
+ }, { children: childrenField });
1442
+ node[childrenField] = nodeList;
1443
+ if (transform) {
1444
+ node[mapChildrenField] = nodeList;
1445
+ }
1446
+ updateAfterDataIndex();
1447
+ return nodeList;
1448
+ });
1449
+ },
1450
+ isExpandByNode,
1451
+ isCheckedByRadioNodeId,
1452
+ isCheckedByRadioNode,
1453
+ isCheckedByCheckboxNodeId,
1454
+ isIndeterminateByCheckboxNode,
1455
+ isCheckedByCheckboxNode,
1456
+ getCheckboxIndeterminateNodes() {
1457
+ const { nodeMaps, indeterminateRowMaps } = internalData;
1458
+ const list = [];
1459
+ XEUtils.each(indeterminateRowMaps, (item, nodeid) => {
1460
+ const nodeItem = nodeMaps[nodeid];
1461
+ if (nodeItem) {
1462
+ list.push(nodeItem.item);
1463
+ }
1464
+ });
1465
+ return list;
1466
+ },
1467
+ recalculate,
1468
+ scrollTo,
1469
+ clearScroll
1470
+ };
1039
1471
  const treePrivateMethods = {};
1040
1472
  Object.assign($xeTree, treeMethods, treePrivateMethods);
1041
1473
  const renderRadio = (node, nodeid, isChecked) => {
1042
1474
  const { showRadio } = props;
1043
1475
  const radioOpts = computeRadioOpts.value;
1044
1476
  const { showIcon, checkMethod, visibleMethod } = radioOpts;
1045
- const isVisible = !visibleMethod || visibleMethod({ node });
1477
+ const isVisible = !visibleMethod || visibleMethod({ $tree: $xeTree, node });
1046
1478
  let isDisabled = !!checkMethod;
1047
1479
  if (showRadio && showIcon && isVisible) {
1048
1480
  if (checkMethod) {
1049
- isDisabled = !checkMethod({ node });
1481
+ isDisabled = !checkMethod({ $tree: $xeTree, node });
1050
1482
  }
1051
1483
  return h('div', {
1052
1484
  class: ['vxe-tree--radio-option', {
@@ -1071,11 +1503,11 @@ export default defineVxeComponent({
1071
1503
  const checkboxOpts = computeCheckboxOpts.value;
1072
1504
  const { showIcon, checkMethod, visibleMethod } = checkboxOpts;
1073
1505
  const isIndeterminate = isIndeterminateByCheckboxNodeid(nodeid);
1074
- const isVisible = !visibleMethod || visibleMethod({ node });
1506
+ const isVisible = !visibleMethod || visibleMethod({ $tree: $xeTree, node });
1075
1507
  let isDisabled = !!checkMethod;
1076
1508
  if (showCheckbox && showIcon && isVisible) {
1077
1509
  if (checkMethod) {
1078
- isDisabled = !checkMethod({ node });
1510
+ isDisabled = !checkMethod({ $tree: $xeTree, node });
1079
1511
  }
1080
1512
  return h('div', {
1081
1513
  class: ['vxe-tree--checkbox-option', {
@@ -1096,10 +1528,10 @@ export default defineVxeComponent({
1096
1528
  }
1097
1529
  return renderEmptyElement($xeTree);
1098
1530
  };
1099
- const renderNode = (node) => {
1531
+ const renderNode = (node, nodeid) => {
1100
1532
  const { lazy, showRadio, showCheckbox, showLine, indent, iconOpen, iconClose, iconLoaded, showIcon } = props;
1101
1533
  const { currentNode, selectRadioKey, updateExpandedFlag } = reactData;
1102
- const { nodeMaps, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData;
1534
+ const { afterTreeList, nodeMaps, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData;
1103
1535
  const childrenField = computeChildrenField.value;
1104
1536
  const titleField = computeTitleField.value;
1105
1537
  const hasChildField = computeHasChildField.value;
@@ -1108,30 +1540,13 @@ export default defineVxeComponent({
1108
1540
  const iconSlot = slots.icon;
1109
1541
  const titleSlot = slots.title;
1110
1542
  const extraSlot = slots.extra;
1111
- const nodeid = getNodeId(node);
1112
1543
  const isExpand = updateExpandedFlag && treeExpandedMaps[nodeid];
1113
1544
  const nodeItem = nodeMaps[nodeid];
1114
1545
  const nodeValue = XEUtils.get(node, titleField);
1115
- const childVns = [];
1116
- if (hasChild && treeExpandedMaps[nodeid]) {
1117
- if (showLine) {
1118
- childVns.push(h('div', {
1119
- key: 'line',
1120
- class: 'vxe-tree--node-child-line',
1121
- style: {
1122
- height: `calc(${nodeItem.lineCount} * var(--vxe-ui-tree-node-height) - var(--vxe-ui-tree-node-height) / 2)`,
1123
- left: `${(nodeItem.level + 1) * (indent || 1)}px`
1124
- }
1125
- }));
1126
- }
1127
- childList.forEach(childItem => {
1128
- childVns.push(renderNode(childItem));
1129
- });
1130
- }
1546
+ const nLevel = nodeItem.level;
1131
1547
  let isRadioChecked = false;
1132
1548
  if (showRadio) {
1133
- // eslint-disable-next-line eqeqeq
1134
- isRadioChecked = nodeid == selectRadioKey;
1549
+ isRadioChecked = nodeid === String(selectRadioKey);
1135
1550
  }
1136
1551
  let isCheckboxChecked = false;
1137
1552
  if (showCheckbox) {
@@ -1145,8 +1560,11 @@ export default defineVxeComponent({
1145
1560
  hasLazyChilds = node[hasChildField];
1146
1561
  isLazyLoaded = !!nodeItem.treeLoaded;
1147
1562
  }
1563
+ const prevNode = nodeItem.items[nodeItem.treeIndex - 1];
1564
+ const nParams = { node, isExpand };
1148
1565
  return h('div', {
1149
- class: ['vxe-tree--node-wrapper', `node--level-${nodeItem.level}`],
1566
+ key: nodeid,
1567
+ class: ['vxe-tree--node-wrapper', `node--level-${nLevel}`],
1150
1568
  nodeid
1151
1569
  }, [
1152
1570
  h('div', {
@@ -1156,7 +1574,7 @@ export default defineVxeComponent({
1156
1574
  'is-checkbox--checked': isCheckboxChecked
1157
1575
  }],
1158
1576
  style: {
1159
- paddingLeft: `${(nodeItem.level - 1) * (indent || 1)}px`
1577
+ paddingLeft: `${(nLevel - 1) * (indent || 1)}px`
1160
1578
  },
1161
1579
  onClick(evnt) {
1162
1580
  handleNodeClickEvent(evnt, node);
@@ -1165,26 +1583,36 @@ export default defineVxeComponent({
1165
1583
  handleNodeDblclickEvent(evnt, node);
1166
1584
  }
1167
1585
  }, [
1168
- showIcon || showLine
1586
+ showLine
1169
1587
  ? h('div', {
1170
- class: 'vxe-tree--node-item-switcher'
1171
- }, showIcon && (lazy ? (isLazyLoaded ? hasChild : hasLazyChilds) : hasChild)
1172
- ? [
1173
- h('div', {
1174
- class: 'vxe-tree--node-item-icon',
1175
- onClick(evnt) {
1176
- toggleExpandEvent(evnt, node);
1177
- }
1178
- }, iconSlot
1179
- ? iconSlot({ node, isExpand })
1180
- : [
1181
- h('i', {
1182
- class: isLazyLoading ? (iconLoaded || getIcon().TREE_NODE_LOADED) : (isExpand ? (iconOpen || getIcon().TREE_NODE_OPEN) : (iconClose || getIcon().TREE_NODE_CLOSE))
1183
- })
1184
- ])
1185
- ]
1186
- : [])
1588
+ class: 'vxe-tree--node-line-wrapper'
1589
+ }, [
1590
+ h('div', {
1591
+ class: 'vxe-tree--node-line',
1592
+ style: {
1593
+ height: `${getNodeId(afterTreeList[0]) === nodeid ? 1 : calcTreeLine($xeTree, node, prevNode)}px`
1594
+ }
1595
+ })
1596
+ ])
1187
1597
  : renderEmptyElement($xeTree),
1598
+ h('div', {
1599
+ class: 'vxe-tree--node-item-switcher'
1600
+ }, showIcon && (lazy ? (isLazyLoaded ? hasChild : hasLazyChilds) : hasChild)
1601
+ ? [
1602
+ h('div', {
1603
+ class: 'vxe-tree--node-item-icon',
1604
+ onClick(evnt) {
1605
+ toggleExpandEvent(evnt, node);
1606
+ }
1607
+ }, iconSlot
1608
+ ? getSlotVNs(iconSlot(nParams))
1609
+ : [
1610
+ h('i', {
1611
+ class: isLazyLoading ? (iconLoaded || getIcon().TREE_NODE_LOADED) : (isExpand ? (iconOpen || getIcon().TREE_NODE_OPEN) : (iconClose || getIcon().TREE_NODE_CLOSE))
1612
+ })
1613
+ ])
1614
+ ]
1615
+ : []),
1188
1616
  renderRadio(node, nodeid, isRadioChecked),
1189
1617
  renderCheckbox(node, nodeid, isCheckboxChecked),
1190
1618
  h('div', {
@@ -1192,36 +1620,56 @@ export default defineVxeComponent({
1192
1620
  }, [
1193
1621
  h('div', {
1194
1622
  class: 'vxe-tree--node-item-title'
1195
- }, titleSlot ? getSlotVNs(titleSlot({ node, isExpand })) : `${nodeValue}`),
1623
+ }, titleSlot ? getSlotVNs(titleSlot(nParams)) : `${nodeValue}`),
1196
1624
  extraSlot
1197
1625
  ? h('div', {
1198
1626
  class: 'vxe-tree--node-item-extra'
1199
- }, getSlotVNs(extraSlot({ node, isExpand })))
1627
+ }, getSlotVNs(extraSlot(nParams)))
1200
1628
  : renderEmptyElement($xeTree)
1201
1629
  ])
1202
- ]),
1203
- hasChild && treeExpandedMaps[nodeid]
1204
- ? h('div', {
1205
- class: 'vxe-tree--node-child-wrapper'
1206
- }, childVns)
1207
- : renderEmptyElement($xeTree)
1630
+ ])
1208
1631
  ]);
1209
1632
  };
1210
- const renderNodeList = () => {
1211
- const { treeList } = reactData;
1212
- return h('div', {
1213
- class: 'vxe-tree--node-list-wrapper'
1214
- }, treeList.map(node => renderNode(node)));
1633
+ const renderList = (treeList) => {
1634
+ const { transform } = props;
1635
+ const { treeExpandedMaps } = internalData;
1636
+ const childrenField = computeChildrenField.value;
1637
+ if (!treeList.length) {
1638
+ return [
1639
+ h('div', {
1640
+ class: 'vxe-tree--empty-placeholder'
1641
+ }, getI18n('vxe.tree.searchEmpty'))
1642
+ ];
1643
+ }
1644
+ const nodeVNs = [];
1645
+ treeList.forEach(transform
1646
+ ? (node) => {
1647
+ const nodeid = getNodeId(node);
1648
+ nodeVNs.push(renderNode(node, nodeid));
1649
+ }
1650
+ : (node) => {
1651
+ const nodeid = getNodeId(node);
1652
+ nodeVNs.push(renderNode(node, nodeid));
1653
+ const childList = XEUtils.get(node, childrenField);
1654
+ const hasChild = childList && childList.length;
1655
+ if (hasChild && treeExpandedMaps[nodeid]) {
1656
+ nodeVNs.push(...renderList(childList));
1657
+ }
1658
+ });
1659
+ return nodeVNs;
1215
1660
  };
1216
1661
  const renderVN = () => {
1217
1662
  const { loading, trigger, showLine } = props;
1663
+ const { bodyHeight, topSpaceHeight, treeList } = reactData;
1218
1664
  const vSize = computeSize.value;
1219
1665
  const radioOpts = computeRadioOpts.value;
1220
1666
  const checkboxOpts = computeCheckboxOpts.value;
1221
- const treeStyle = computeTreeStyle.value;
1222
1667
  const loadingOpts = computeLoadingOpts.value;
1223
1668
  const isRowHover = computeIsRowHover.value;
1669
+ const treeStyle = computeTreeStyle.value;
1224
1670
  const loadingSlot = slots.loading;
1671
+ const headerSlot = slots.header;
1672
+ const footerSlot = slots.footer;
1225
1673
  return h('div', {
1226
1674
  ref: refElem,
1227
1675
  class: ['vxe-tree', {
@@ -1232,10 +1680,40 @@ export default defineVxeComponent({
1232
1680
  'node--hover': isRowHover,
1233
1681
  'node--trigger': trigger === 'node',
1234
1682
  'is--loading': loading
1235
- }],
1236
- style: treeStyle
1683
+ }]
1237
1684
  }, [
1238
- renderNodeList(),
1685
+ headerSlot
1686
+ ? h('div', {
1687
+ ref: refHeaderWrapperElem,
1688
+ class: 'vxe-tree--header-wrapper'
1689
+ }, headerSlot({ $tree: $xeTree }))
1690
+ : renderEmptyElement($xeTree),
1691
+ h('div', {
1692
+ ref: refVirtualWrapper,
1693
+ class: 'vxe-tree--node-list-wrapper',
1694
+ style: treeStyle,
1695
+ onScroll: scrollEvent
1696
+ }, [
1697
+ h('div', {
1698
+ class: 'vxe-tree--y-space',
1699
+ style: {
1700
+ height: bodyHeight ? `${bodyHeight}px` : ''
1701
+ }
1702
+ }),
1703
+ h('div', {
1704
+ ref: refVirtualBody,
1705
+ class: 'vxe-tree--node-list-body',
1706
+ style: {
1707
+ transform: `translateY(${topSpaceHeight}px)`
1708
+ }
1709
+ }, renderList(treeList))
1710
+ ]),
1711
+ footerSlot
1712
+ ? h('div', {
1713
+ ref: refFooterWrapperElem,
1714
+ class: 'vxe-tree--footer-wrapper'
1715
+ }, footerSlot({ $tree: $xeTree }))
1716
+ : renderEmptyElement($xeTree),
1239
1717
  /**
1240
1718
  * 加载中
1241
1719
  */
@@ -1259,7 +1737,7 @@ export default defineVxeComponent({
1259
1737
  dataFlag.value++;
1260
1738
  });
1261
1739
  watch(dataFlag, () => {
1262
- loadTreeData(props.data || []);
1740
+ loadData(props.data || []);
1263
1741
  });
1264
1742
  watch(() => props.checkNodeKey, (val) => {
1265
1743
  reactData.selectRadioKey = val;
@@ -1274,13 +1752,52 @@ export default defineVxeComponent({
1274
1752
  watch(checkboxFlag, () => {
1275
1753
  updateCheckboxChecked(props.checkNodeKeys || []);
1276
1754
  });
1755
+ watch(() => props.filterValue, () => {
1756
+ triggerSearchEvent(new Event('filter'));
1757
+ });
1758
+ const hFlag = ref(0);
1759
+ watch(() => props.height, () => {
1760
+ hFlag.value++;
1761
+ });
1762
+ watch(() => props.minHeight, () => {
1763
+ hFlag.value++;
1764
+ });
1765
+ watch(() => props.maxHeight, () => {
1766
+ hFlag.value++;
1767
+ });
1768
+ watch(hFlag, () => {
1769
+ recalculate();
1770
+ });
1771
+ onMounted(() => {
1772
+ if (props.autoResize) {
1773
+ const el = refElem.value;
1774
+ const parentEl = getParentElem();
1775
+ const resizeObserver = globalResize.create(() => {
1776
+ if (props.autoResize) {
1777
+ recalculate();
1778
+ }
1779
+ });
1780
+ if (el) {
1781
+ resizeObserver.observe(el);
1782
+ }
1783
+ if (parentEl) {
1784
+ resizeObserver.observe(parentEl);
1785
+ }
1786
+ internalData.resizeObserver = resizeObserver;
1787
+ }
1788
+ globalEvents.on($xeTree, 'resize', handleGlobalResizeEvent);
1789
+ });
1277
1790
  onUnmounted(() => {
1278
- reactData.treeList = [];
1791
+ const { resizeObserver } = internalData;
1792
+ if (resizeObserver) {
1793
+ resizeObserver.disconnect();
1794
+ }
1279
1795
  internalData.treeExpandedMaps = {};
1280
1796
  internalData.indeterminateRowMaps = {};
1281
1797
  internalData.nodeMaps = {};
1798
+ globalEvents.off($xeTree, 'resize');
1282
1799
  });
1283
- loadTreeData(props.data || []);
1800
+ loadData(props.data || []);
1284
1801
  $xeTree.renderVN = renderVN;
1285
1802
  return $xeTree;
1286
1803
  },