vxe-pc-ui 4.7.5 → 4.7.6

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 +918 -407
  31. package/es/tree/src/util.js +32 -0
  32. package/es/tree/style.css +23 -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 +23 -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 +1505 -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 +1147 -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 +23 -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 +23 -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 +941 -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 +28 -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.1752416456948.ttf} +0 -0
  187. /package/es/icon/{iconfont.1752151733538.woff → iconfont.1752416456948.woff} +0 -0
  188. /package/es/icon/{iconfont.1752151733538.woff2 → iconfont.1752416456948.woff2} +0 -0
  189. /package/es/{iconfont.1752151733538.ttf → iconfont.1752416456948.ttf} +0 -0
  190. /package/es/{iconfont.1752151733538.woff → iconfont.1752416456948.woff} +0 -0
  191. /package/es/{iconfont.1752151733538.woff2 → iconfont.1752416456948.woff2} +0 -0
  192. /package/lib/icon/style/{iconfont.1752151733538.ttf → iconfont.1752416456948.ttf} +0 -0
  193. /package/lib/icon/style/{iconfont.1752151733538.woff → iconfont.1752416456948.woff} +0 -0
  194. /package/lib/icon/style/{iconfont.1752151733538.woff2 → iconfont.1752416456948.woff2} +0 -0
  195. /package/lib/{iconfont.1752151733538.ttf → iconfont.1752416456948.ttf} +0 -0
  196. /package/lib/{iconfont.1752151733538.woff → iconfont.1752416456948.woff} +0 -0
  197. /package/lib/{iconfont.1752151733538.woff2 → iconfont.1752416456948.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,368 @@ 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();
661
760
  }
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);
761
+ return nextTick();
762
+ };
763
+ const loadYData = (evnt) => {
764
+ const { scrollYStore } = internalData;
765
+ const { startIndex, endIndex, visibleSize, offsetSize, rowHeight } = scrollYStore;
766
+ const scrollBodyElem = evnt.target;
767
+ const scrollTop = scrollBodyElem.scrollTop;
768
+ const toVisibleIndex = Math.floor(scrollTop / rowHeight);
769
+ const offsetStartIndex = Math.max(0, toVisibleIndex - 1 - offsetSize);
770
+ const offsetEndIndex = toVisibleIndex + visibleSize + offsetSize;
771
+ if (toVisibleIndex <= startIndex || toVisibleIndex >= endIndex - visibleSize - 1) {
772
+ if (startIndex !== offsetStartIndex || endIndex !== offsetEndIndex) {
773
+ scrollYStore.startIndex = offsetStartIndex;
774
+ scrollYStore.endIndex = offsetEndIndex;
775
+ updateYData();
670
776
  }
671
777
  }
672
778
  };
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
- });
779
+ const scrollEvent = (evnt) => {
780
+ const scrollBodyElem = evnt.target;
781
+ const scrollTop = scrollBodyElem.scrollTop;
782
+ const scrollLeft = scrollBodyElem.scrollLeft;
783
+ const isX = scrollLeft !== internalData.lastScrollLeft;
784
+ const isY = scrollTop !== internalData.lastScrollTop;
785
+ internalData.lastScrollTop = scrollTop;
786
+ internalData.lastScrollLeft = scrollLeft;
787
+ if (reactData.scrollYLoad) {
788
+ loadYData(evnt);
684
789
  }
790
+ internalData.lastScrollTime = Date.now();
791
+ dispatchEvent('scroll', { scrollLeft, scrollTop, isX, isY }, evnt);
685
792
  };
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
- }
793
+ const clearScroll = () => {
794
+ const scrollBodyElem = refVirtualWrapper.value;
795
+ if (scrollBodyElem) {
796
+ scrollBodyElem.scrollTop = 0;
797
+ scrollBodyElem.scrollLeft = 0;
701
798
  }
799
+ internalData.lastScrollTop = 0;
800
+ internalData.lastScrollLeft = 0;
801
+ return nextTick();
702
802
  };
703
803
  const handleNodeClickEvent = (evnt, node) => {
704
804
  const { showRadio, showCheckbox, trigger } = props;
@@ -763,13 +863,11 @@ export default defineVxeComponent({
763
863
  if (!checkStrictly && $xeTree.isCheckedByCheckboxNodeId(nodeid)) {
764
864
  handleCheckedCheckboxNode(childRows, true);
765
865
  }
766
- updateNodeLine(node);
767
866
  dispatchEvent('load-success', { node, data: childRecords }, new Event('load-success'));
768
867
  return nextTick();
769
868
  });
770
869
  }
771
870
  else {
772
- updateNodeLine(node);
773
871
  dispatchEvent('load-success', { node, data: childRecords }, new Event('load-success'));
774
872
  }
775
873
  }).catch((e) => {
@@ -778,10 +876,11 @@ export default defineVxeComponent({
778
876
  if (treeExpandLazyLoadedMaps[nodeid]) {
779
877
  treeExpandLazyLoadedMaps[nodeid] = false;
780
878
  }
781
- updateNodeLine(node);
782
879
  dispatchEvent('load-error', { node, data: e }, new Event('load-error'));
783
880
  }).finally(() => {
784
- return nextTick();
881
+ handleTreeToList();
882
+ handleData();
883
+ return recalculate();
785
884
  });
786
885
  }
787
886
  else {
@@ -847,8 +946,9 @@ export default defineVxeComponent({
847
946
  });
848
947
  }
849
948
  reactData.updateExpandedFlag++;
850
- expandNodes.forEach(updateNodeLine);
851
- return Promise.all(result);
949
+ handleTreeToList();
950
+ handleData();
951
+ return Promise.all(result).then(() => recalculate());
852
952
  };
853
953
  const toggleExpandEvent = (evnt, node) => {
854
954
  const { lazy } = props;
@@ -862,8 +962,7 @@ export default defineVxeComponent({
862
962
  };
863
963
  const updateCheckboxStatus = () => {
864
964
  const { transform } = props;
865
- const { treeList } = reactData;
866
- const { selectCheckboxMaps, indeterminateRowMaps } = internalData;
965
+ const { selectCheckboxMaps, indeterminateRowMaps, afterTreeList } = internalData;
867
966
  const childrenField = computeChildrenField.value;
868
967
  const mapChildrenField = computeMapChildrenField.value;
869
968
  const checkboxOpts = computeCheckboxOpts.value;
@@ -871,7 +970,7 @@ export default defineVxeComponent({
871
970
  if (!checkStrictly) {
872
971
  const childRowMaps = {};
873
972
  const childRowList = [];
874
- XEUtils.eachTree(treeList, (node) => {
973
+ XEUtils.eachTree(afterTreeList, (node) => {
875
974
  const nodeid = getNodeId(node);
876
975
  const childList = node[childrenField];
877
976
  if (childList && childList.length && !childRowMaps[nodeid]) {
@@ -885,12 +984,13 @@ export default defineVxeComponent({
885
984
  const childList = vals[2];
886
985
  let sLen = 0; // 已选
887
986
  let hLen = 0; // 半选
888
- let vLen = 0; // 有效行
987
+ let vLen = 0; // 有效子行
988
+ const cLen = childList.length; // 子行
889
989
  childList.forEach(checkMethod
890
990
  ? (item) => {
891
991
  const childNodeid = getNodeId(item);
892
992
  const isSelect = selectCheckboxMaps[childNodeid];
893
- if (checkMethod({ node: item })) {
993
+ if (checkMethod({ $tree: $xeTree, node: item })) {
894
994
  if (isSelect) {
895
995
  sLen++;
896
996
  }
@@ -919,8 +1019,29 @@ export default defineVxeComponent({
919
1019
  }
920
1020
  vLen++;
921
1021
  });
922
- const isSelected = sLen >= vLen;
923
- const halfSelect = !isSelected && (sLen >= 1 || hLen >= 1);
1022
+ let isSelected = false;
1023
+ if (cLen > 0) {
1024
+ if (vLen > 0) {
1025
+ isSelected = (sLen > 0 || hLen > 0) && sLen >= vLen;
1026
+ }
1027
+ else {
1028
+ // 如果存在子项禁用
1029
+ if ((sLen > 0 && sLen >= vLen)) {
1030
+ isSelected = true;
1031
+ }
1032
+ else if (selectCheckboxMaps[nodeid]) {
1033
+ isSelected = true;
1034
+ }
1035
+ else {
1036
+ isSelected = false;
1037
+ }
1038
+ }
1039
+ }
1040
+ else {
1041
+ // 如果无子项
1042
+ isSelected = selectCheckboxMaps[nodeid];
1043
+ }
1044
+ const halfSelect = !isSelected && (sLen > 0 || hLen > 0);
924
1045
  if (isSelected) {
925
1046
  selectCheckboxMaps[nodeid] = node;
926
1047
  if (indeterminateRowMaps[nodeid]) {
@@ -955,7 +1076,7 @@ export default defineVxeComponent({
955
1076
  const { checkStrictly, checkMethod } = checkboxOpts;
956
1077
  let isDisabled = !!checkMethod;
957
1078
  if (checkMethod) {
958
- isDisabled = !checkMethod({ node });
1079
+ isDisabled = !checkMethod({ $tree: $xeTree, node });
959
1080
  }
960
1081
  if (isDisabled) {
961
1082
  return;
@@ -970,7 +1091,7 @@ export default defineVxeComponent({
970
1091
  selectCheckboxMaps[nodeid] = node;
971
1092
  }
972
1093
  if (!checkStrictly) {
973
- XEUtils.eachTree(XEUtils.get(node, childrenField), (childNode) => {
1094
+ XEUtils.eachTree(XEUtils.get(node, transform ? mapChildrenField : childrenField), (childNode) => {
974
1095
  const childNodeid = getNodeId(childNode);
975
1096
  if (isChecked) {
976
1097
  if (!selectCheckboxMaps[childNodeid]) {
@@ -1025,7 +1146,7 @@ export default defineVxeComponent({
1025
1146
  const { checkMethod } = radioOpts;
1026
1147
  let isDisabled = !!checkMethod;
1027
1148
  if (checkMethod) {
1028
- isDisabled = !checkMethod({ node });
1149
+ isDisabled = !checkMethod({ $tree: $xeTree, node });
1029
1150
  }
1030
1151
  if (isDisabled) {
1031
1152
  return;
@@ -1036,17 +1157,322 @@ export default defineVxeComponent({
1036
1157
  emitRadioMode(value);
1037
1158
  dispatchEvent('radio-change', { node, value, checked: isChecked }, evnt);
1038
1159
  };
1160
+ const handleGlobalResizeEvent = () => {
1161
+ const el = refElem.value;
1162
+ if (!el || !el.clientWidth) {
1163
+ return;
1164
+ }
1165
+ recalculate();
1166
+ };
1167
+ const treeMethods = {
1168
+ dispatchEvent,
1169
+ getNodeId,
1170
+ loadData(data) {
1171
+ return loadData(data || []);
1172
+ },
1173
+ reloadData(data) {
1174
+ return loadData(data || []);
1175
+ },
1176
+ clearCurrentNode() {
1177
+ reactData.currentNode = null;
1178
+ return nextTick();
1179
+ },
1180
+ getCurrentNodeId() {
1181
+ const { currentNode } = reactData;
1182
+ if (currentNode) {
1183
+ return getNodeId(currentNode);
1184
+ }
1185
+ return null;
1186
+ },
1187
+ getCurrentNode() {
1188
+ const { currentNode } = reactData;
1189
+ const { nodeMaps } = internalData;
1190
+ if (currentNode) {
1191
+ const nodeItem = nodeMaps[getNodeId(currentNode)];
1192
+ if (nodeItem) {
1193
+ return nodeItem.item;
1194
+ }
1195
+ }
1196
+ return null;
1197
+ },
1198
+ setCurrentNodeId(nodeKey) {
1199
+ const { nodeMaps } = internalData;
1200
+ const nodeItem = nodeMaps[nodeKey];
1201
+ reactData.currentNode = nodeItem ? nodeItem.item : null;
1202
+ return nextTick();
1203
+ },
1204
+ setCurrentNode(node) {
1205
+ reactData.currentNode = node;
1206
+ return nextTick();
1207
+ },
1208
+ clearRadioNode() {
1209
+ reactData.selectRadioKey = null;
1210
+ return nextTick();
1211
+ },
1212
+ getRadioNodeId() {
1213
+ return reactData.selectRadioKey || null;
1214
+ },
1215
+ getRadioNode() {
1216
+ const { selectRadioKey } = reactData;
1217
+ const { nodeMaps } = internalData;
1218
+ if (selectRadioKey) {
1219
+ const nodeItem = nodeMaps[selectRadioKey];
1220
+ if (nodeItem) {
1221
+ return nodeItem.item;
1222
+ }
1223
+ }
1224
+ return null;
1225
+ },
1226
+ setRadioNodeId(nodeKey) {
1227
+ reactData.selectRadioKey = nodeKey;
1228
+ return nextTick();
1229
+ },
1230
+ setRadioNode,
1231
+ setCheckboxNode,
1232
+ setCheckboxByNodeId,
1233
+ getCheckboxNodeIds() {
1234
+ const { selectCheckboxMaps } = internalData;
1235
+ return Object.keys(selectCheckboxMaps);
1236
+ },
1237
+ getCheckboxNodes() {
1238
+ const { nodeMaps, selectCheckboxMaps } = internalData;
1239
+ const list = [];
1240
+ XEUtils.each(selectCheckboxMaps, (item, nodeid) => {
1241
+ const nodeItem = nodeMaps[nodeid];
1242
+ if (nodeItem) {
1243
+ list.push(nodeItem.item);
1244
+ }
1245
+ });
1246
+ return list;
1247
+ },
1248
+ clearCheckboxNode() {
1249
+ internalData.selectCheckboxMaps = {};
1250
+ reactData.updateCheckboxFlag++;
1251
+ return nextTick().then(() => {
1252
+ return { checkNodeKeys: [] };
1253
+ });
1254
+ },
1255
+ setAllCheckboxNode(checked) {
1256
+ const { transform } = props;
1257
+ const selectMaps = {};
1258
+ const childrenField = computeChildrenField.value;
1259
+ const mapChildrenField = computeMapChildrenField.value;
1260
+ const checkKeys = [];
1261
+ if (checked) {
1262
+ XEUtils.eachTree(internalData.afterTreeList, (node) => {
1263
+ const nodeid = getNodeId(node);
1264
+ checkKeys.push(nodeid);
1265
+ selectMaps[nodeid] = true;
1266
+ }, { children: transform ? mapChildrenField : childrenField });
1267
+ }
1268
+ internalData.selectCheckboxMaps = selectMaps;
1269
+ reactData.updateCheckboxFlag++;
1270
+ return nextTick().then(() => {
1271
+ return { checkNodeKeys: checkKeys };
1272
+ });
1273
+ },
1274
+ clearExpandNode() {
1275
+ return treeMethods.clearAllExpandNode();
1276
+ },
1277
+ clearAllExpandNode() {
1278
+ const { nodeMaps } = internalData;
1279
+ XEUtils.each(nodeMaps, (nodeItem) => {
1280
+ nodeItem.treeLoaded = false;
1281
+ });
1282
+ internalData.treeExpandedMaps = {};
1283
+ reactData.updateExpandedFlag++;
1284
+ handleTreeToList();
1285
+ handleData();
1286
+ return recalculate();
1287
+ },
1288
+ setExpandByNodeId(nodeids, expanded) {
1289
+ const { treeExpandedMaps } = internalData;
1290
+ if (nodeids) {
1291
+ if (!XEUtils.isArray(nodeids)) {
1292
+ nodeids = [nodeids];
1293
+ }
1294
+ nodeids.forEach((nodeid) => {
1295
+ handleSetExpand(nodeid, expanded, treeExpandedMaps);
1296
+ });
1297
+ reactData.updateExpandedFlag++;
1298
+ }
1299
+ handleTreeToList();
1300
+ handleData();
1301
+ return recalculate();
1302
+ },
1303
+ getExpandNodeIds() {
1304
+ const { treeExpandedMaps } = internalData;
1305
+ return XEUtils.keys(treeExpandedMaps);
1306
+ },
1307
+ getExpandNodes() {
1308
+ const { nodeMaps, treeExpandedMaps } = internalData;
1309
+ const list = [];
1310
+ XEUtils.each(treeExpandedMaps, (item, nodeid) => {
1311
+ const nodeItem = nodeMaps[nodeid];
1312
+ if (nodeItem) {
1313
+ list.push(nodeItem.item);
1314
+ }
1315
+ });
1316
+ return list;
1317
+ },
1318
+ setExpandNode(nodes, expanded) {
1319
+ const { treeExpandedMaps } = internalData;
1320
+ if (nodes) {
1321
+ if (!XEUtils.isArray(nodes)) {
1322
+ nodes = [nodes];
1323
+ }
1324
+ nodes.forEach((node) => {
1325
+ const nodeid = getNodeId(node);
1326
+ handleSetExpand(nodeid, expanded, treeExpandedMaps);
1327
+ });
1328
+ reactData.updateExpandedFlag++;
1329
+ }
1330
+ handleTreeToList();
1331
+ handleData();
1332
+ return recalculate();
1333
+ },
1334
+ toggleExpandByNodeId(nodeids) {
1335
+ const { treeExpandedMaps } = internalData;
1336
+ if (nodeids) {
1337
+ if (!XEUtils.isArray(nodeids)) {
1338
+ nodeids = [nodeids];
1339
+ }
1340
+ nodeids.forEach((nodeid) => {
1341
+ handleSetExpand(nodeid, !treeExpandedMaps[nodeid], treeExpandedMaps);
1342
+ });
1343
+ reactData.updateExpandedFlag++;
1344
+ }
1345
+ handleTreeToList();
1346
+ handleData();
1347
+ return recalculate();
1348
+ },
1349
+ toggleExpandNode(nodes) {
1350
+ const { treeExpandedMaps } = internalData;
1351
+ if (nodes) {
1352
+ if (!XEUtils.isArray(nodes)) {
1353
+ nodes = [nodes];
1354
+ }
1355
+ nodes.forEach((node) => {
1356
+ const nodeid = getNodeId(node);
1357
+ handleSetExpand(nodeid, !treeExpandedMaps[nodeid], treeExpandedMaps);
1358
+ });
1359
+ reactData.updateExpandedFlag++;
1360
+ }
1361
+ handleTreeToList();
1362
+ handleData();
1363
+ return recalculate();
1364
+ },
1365
+ setAllExpandNode(expanded) {
1366
+ const { transform } = props;
1367
+ const { treeExpandedMaps } = internalData;
1368
+ const childrenField = computeChildrenField.value;
1369
+ const mapChildrenField = computeMapChildrenField.value;
1370
+ if (expanded) {
1371
+ XEUtils.eachTree(internalData.afterTreeList, (node) => {
1372
+ const childList = XEUtils.get(node, childrenField);
1373
+ const hasChild = childList && childList.length;
1374
+ if (hasChild) {
1375
+ const nodeid = getNodeId(node);
1376
+ treeExpandedMaps[nodeid] = true;
1377
+ }
1378
+ }, { children: transform ? mapChildrenField : childrenField });
1379
+ }
1380
+ else {
1381
+ internalData.treeExpandedMaps = {};
1382
+ }
1383
+ reactData.updateExpandedFlag++;
1384
+ handleTreeToList();
1385
+ handleData();
1386
+ return recalculate();
1387
+ },
1388
+ reloadExpandNode(node) {
1389
+ const { lazy } = props;
1390
+ if (lazy) {
1391
+ treeMethods.clearExpandLoaded(node);
1392
+ return handleAsyncTreeExpandChilds(node);
1393
+ }
1394
+ return recalculate();
1395
+ },
1396
+ clearExpandLoaded(node) {
1397
+ const { lazy } = props;
1398
+ const { nodeMaps } = internalData;
1399
+ if (lazy) {
1400
+ const nodeItem = nodeMaps[getNodeId(node)];
1401
+ if (nodeItem) {
1402
+ nodeItem.treeLoaded = false;
1403
+ }
1404
+ }
1405
+ return recalculate();
1406
+ },
1407
+ /**
1408
+ * 用于树结构,给行数据加载子节点
1409
+ */
1410
+ loadChildrenNode(node, childRecords) {
1411
+ const { lazy, transform } = props;
1412
+ const { nodeMaps } = internalData;
1413
+ if (!lazy) {
1414
+ return Promise.resolve([]);
1415
+ }
1416
+ const childrenField = computeChildrenField.value;
1417
+ const mapChildrenField = computeMapChildrenField.value;
1418
+ const parentNodeItem = nodeMaps[getNodeId(node)];
1419
+ const parentLevel = parentNodeItem ? parentNodeItem.level : 0;
1420
+ const parentNodes = parentNodeItem ? parentNodeItem.nodes : [];
1421
+ return createNode(childRecords).then((nodeList) => {
1422
+ XEUtils.eachTree(nodeList, (childRow, index, items, path, parent, nodes) => {
1423
+ const itemNodeId = getNodeId(childRow);
1424
+ nodeMaps[itemNodeId] = {
1425
+ item: node,
1426
+ index: -1,
1427
+ items,
1428
+ parent: parent || parentNodeItem.item,
1429
+ nodes: parentNodes.concat(nodes),
1430
+ level: parentLevel + nodes.length,
1431
+ treeIndex: -1,
1432
+ lineCount: 0,
1433
+ treeLoaded: false
1434
+ };
1435
+ }, { children: childrenField });
1436
+ node[childrenField] = nodeList;
1437
+ if (transform) {
1438
+ node[mapChildrenField] = nodeList;
1439
+ }
1440
+ updateAfterDataIndex();
1441
+ return nodeList;
1442
+ });
1443
+ },
1444
+ isExpandByNode,
1445
+ isCheckedByRadioNodeId,
1446
+ isCheckedByRadioNode,
1447
+ isCheckedByCheckboxNodeId,
1448
+ isIndeterminateByCheckboxNode,
1449
+ isCheckedByCheckboxNode,
1450
+ getCheckboxIndeterminateNodes() {
1451
+ const { nodeMaps, indeterminateRowMaps } = internalData;
1452
+ const list = [];
1453
+ XEUtils.each(indeterminateRowMaps, (item, nodeid) => {
1454
+ const nodeItem = nodeMaps[nodeid];
1455
+ if (nodeItem) {
1456
+ list.push(nodeItem.item);
1457
+ }
1458
+ });
1459
+ return list;
1460
+ },
1461
+ recalculate,
1462
+ scrollTo,
1463
+ clearScroll
1464
+ };
1039
1465
  const treePrivateMethods = {};
1040
1466
  Object.assign($xeTree, treeMethods, treePrivateMethods);
1041
1467
  const renderRadio = (node, nodeid, isChecked) => {
1042
1468
  const { showRadio } = props;
1043
1469
  const radioOpts = computeRadioOpts.value;
1044
1470
  const { showIcon, checkMethod, visibleMethod } = radioOpts;
1045
- const isVisible = !visibleMethod || visibleMethod({ node });
1471
+ const isVisible = !visibleMethod || visibleMethod({ $tree: $xeTree, node });
1046
1472
  let isDisabled = !!checkMethod;
1047
1473
  if (showRadio && showIcon && isVisible) {
1048
1474
  if (checkMethod) {
1049
- isDisabled = !checkMethod({ node });
1475
+ isDisabled = !checkMethod({ $tree: $xeTree, node });
1050
1476
  }
1051
1477
  return h('div', {
1052
1478
  class: ['vxe-tree--radio-option', {
@@ -1071,11 +1497,11 @@ export default defineVxeComponent({
1071
1497
  const checkboxOpts = computeCheckboxOpts.value;
1072
1498
  const { showIcon, checkMethod, visibleMethod } = checkboxOpts;
1073
1499
  const isIndeterminate = isIndeterminateByCheckboxNodeid(nodeid);
1074
- const isVisible = !visibleMethod || visibleMethod({ node });
1500
+ const isVisible = !visibleMethod || visibleMethod({ $tree: $xeTree, node });
1075
1501
  let isDisabled = !!checkMethod;
1076
1502
  if (showCheckbox && showIcon && isVisible) {
1077
1503
  if (checkMethod) {
1078
- isDisabled = !checkMethod({ node });
1504
+ isDisabled = !checkMethod({ $tree: $xeTree, node });
1079
1505
  }
1080
1506
  return h('div', {
1081
1507
  class: ['vxe-tree--checkbox-option', {
@@ -1096,10 +1522,10 @@ export default defineVxeComponent({
1096
1522
  }
1097
1523
  return renderEmptyElement($xeTree);
1098
1524
  };
1099
- const renderNode = (node) => {
1525
+ const renderNode = (node, nodeid) => {
1100
1526
  const { lazy, showRadio, showCheckbox, showLine, indent, iconOpen, iconClose, iconLoaded, showIcon } = props;
1101
1527
  const { currentNode, selectRadioKey, updateExpandedFlag } = reactData;
1102
- const { nodeMaps, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData;
1528
+ const { afterTreeList, nodeMaps, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData;
1103
1529
  const childrenField = computeChildrenField.value;
1104
1530
  const titleField = computeTitleField.value;
1105
1531
  const hasChildField = computeHasChildField.value;
@@ -1108,30 +1534,13 @@ export default defineVxeComponent({
1108
1534
  const iconSlot = slots.icon;
1109
1535
  const titleSlot = slots.title;
1110
1536
  const extraSlot = slots.extra;
1111
- const nodeid = getNodeId(node);
1112
1537
  const isExpand = updateExpandedFlag && treeExpandedMaps[nodeid];
1113
1538
  const nodeItem = nodeMaps[nodeid];
1114
1539
  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
- }
1540
+ const nLevel = nodeItem.level;
1131
1541
  let isRadioChecked = false;
1132
1542
  if (showRadio) {
1133
- // eslint-disable-next-line eqeqeq
1134
- isRadioChecked = nodeid == selectRadioKey;
1543
+ isRadioChecked = nodeid === String(selectRadioKey);
1135
1544
  }
1136
1545
  let isCheckboxChecked = false;
1137
1546
  if (showCheckbox) {
@@ -1145,8 +1554,11 @@ export default defineVxeComponent({
1145
1554
  hasLazyChilds = node[hasChildField];
1146
1555
  isLazyLoaded = !!nodeItem.treeLoaded;
1147
1556
  }
1557
+ const prevNode = nodeItem.items[nodeItem.treeIndex - 1];
1558
+ const nParams = { node, isExpand };
1148
1559
  return h('div', {
1149
- class: ['vxe-tree--node-wrapper', `node--level-${nodeItem.level}`],
1560
+ key: nodeid,
1561
+ class: ['vxe-tree--node-wrapper', `node--level-${nLevel}`],
1150
1562
  nodeid
1151
1563
  }, [
1152
1564
  h('div', {
@@ -1156,7 +1568,7 @@ export default defineVxeComponent({
1156
1568
  'is-checkbox--checked': isCheckboxChecked
1157
1569
  }],
1158
1570
  style: {
1159
- paddingLeft: `${(nodeItem.level - 1) * (indent || 1)}px`
1571
+ paddingLeft: `${(nLevel - 1) * (indent || 1)}px`
1160
1572
  },
1161
1573
  onClick(evnt) {
1162
1574
  handleNodeClickEvent(evnt, node);
@@ -1165,26 +1577,36 @@ export default defineVxeComponent({
1165
1577
  handleNodeDblclickEvent(evnt, node);
1166
1578
  }
1167
1579
  }, [
1168
- showIcon || showLine
1580
+ showLine
1169
1581
  ? 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
- : [])
1582
+ class: 'vxe-tree--node-line-wrapper'
1583
+ }, [
1584
+ h('div', {
1585
+ class: 'vxe-tree--node-line',
1586
+ style: {
1587
+ height: `${getNodeId(afterTreeList[0]) === nodeid ? 1 : calcTreeLine($xeTree, node, prevNode)}px`
1588
+ }
1589
+ })
1590
+ ])
1187
1591
  : renderEmptyElement($xeTree),
1592
+ h('div', {
1593
+ class: 'vxe-tree--node-item-switcher'
1594
+ }, showIcon && (lazy ? (isLazyLoaded ? hasChild : hasLazyChilds) : hasChild)
1595
+ ? [
1596
+ h('div', {
1597
+ class: 'vxe-tree--node-item-icon',
1598
+ onClick(evnt) {
1599
+ toggleExpandEvent(evnt, node);
1600
+ }
1601
+ }, iconSlot
1602
+ ? getSlotVNs(iconSlot(nParams))
1603
+ : [
1604
+ h('i', {
1605
+ class: isLazyLoading ? (iconLoaded || getIcon().TREE_NODE_LOADED) : (isExpand ? (iconOpen || getIcon().TREE_NODE_OPEN) : (iconClose || getIcon().TREE_NODE_CLOSE))
1606
+ })
1607
+ ])
1608
+ ]
1609
+ : []),
1188
1610
  renderRadio(node, nodeid, isRadioChecked),
1189
1611
  renderCheckbox(node, nodeid, isCheckboxChecked),
1190
1612
  h('div', {
@@ -1192,36 +1614,56 @@ export default defineVxeComponent({
1192
1614
  }, [
1193
1615
  h('div', {
1194
1616
  class: 'vxe-tree--node-item-title'
1195
- }, titleSlot ? getSlotVNs(titleSlot({ node, isExpand })) : `${nodeValue}`),
1617
+ }, titleSlot ? getSlotVNs(titleSlot(nParams)) : `${nodeValue}`),
1196
1618
  extraSlot
1197
1619
  ? h('div', {
1198
1620
  class: 'vxe-tree--node-item-extra'
1199
- }, getSlotVNs(extraSlot({ node, isExpand })))
1621
+ }, getSlotVNs(extraSlot(nParams)))
1200
1622
  : renderEmptyElement($xeTree)
1201
1623
  ])
1202
- ]),
1203
- hasChild && treeExpandedMaps[nodeid]
1204
- ? h('div', {
1205
- class: 'vxe-tree--node-child-wrapper'
1206
- }, childVns)
1207
- : renderEmptyElement($xeTree)
1624
+ ])
1208
1625
  ]);
1209
1626
  };
1210
- const renderNodeList = () => {
1211
- const { treeList } = reactData;
1212
- return h('div', {
1213
- class: 'vxe-tree--node-list-wrapper'
1214
- }, treeList.map(node => renderNode(node)));
1627
+ const renderList = (treeList) => {
1628
+ const { transform } = props;
1629
+ const { treeExpandedMaps } = internalData;
1630
+ const childrenField = computeChildrenField.value;
1631
+ if (!treeList.length) {
1632
+ return [
1633
+ h('div', {
1634
+ class: 'vxe-tree--empty-placeholder'
1635
+ }, getI18n('vxe.tree.searchEmpty'))
1636
+ ];
1637
+ }
1638
+ const nodeVNs = [];
1639
+ treeList.forEach(transform
1640
+ ? (node) => {
1641
+ const nodeid = getNodeId(node);
1642
+ nodeVNs.push(renderNode(node, nodeid));
1643
+ }
1644
+ : (node) => {
1645
+ const nodeid = getNodeId(node);
1646
+ nodeVNs.push(renderNode(node, nodeid));
1647
+ const childList = XEUtils.get(node, childrenField);
1648
+ const hasChild = childList && childList.length;
1649
+ if (hasChild && treeExpandedMaps[nodeid]) {
1650
+ nodeVNs.push(...renderList(childList));
1651
+ }
1652
+ });
1653
+ return nodeVNs;
1215
1654
  };
1216
1655
  const renderVN = () => {
1217
1656
  const { loading, trigger, showLine } = props;
1657
+ const { bodyHeight, topSpaceHeight, treeList } = reactData;
1218
1658
  const vSize = computeSize.value;
1219
1659
  const radioOpts = computeRadioOpts.value;
1220
1660
  const checkboxOpts = computeCheckboxOpts.value;
1221
- const treeStyle = computeTreeStyle.value;
1222
1661
  const loadingOpts = computeLoadingOpts.value;
1223
1662
  const isRowHover = computeIsRowHover.value;
1663
+ const treeStyle = computeTreeStyle.value;
1224
1664
  const loadingSlot = slots.loading;
1665
+ const headerSlot = slots.header;
1666
+ const footerSlot = slots.footer;
1225
1667
  return h('div', {
1226
1668
  ref: refElem,
1227
1669
  class: ['vxe-tree', {
@@ -1232,10 +1674,40 @@ export default defineVxeComponent({
1232
1674
  'node--hover': isRowHover,
1233
1675
  'node--trigger': trigger === 'node',
1234
1676
  'is--loading': loading
1235
- }],
1236
- style: treeStyle
1677
+ }]
1237
1678
  }, [
1238
- renderNodeList(),
1679
+ headerSlot
1680
+ ? h('div', {
1681
+ ref: refHeaderWrapperElem,
1682
+ class: 'vxe-tree--header-wrapper'
1683
+ }, headerSlot({ $tree: $xeTree }))
1684
+ : renderEmptyElement($xeTree),
1685
+ h('div', {
1686
+ ref: refVirtualWrapper,
1687
+ class: 'vxe-tree--node-list-wrapper',
1688
+ style: treeStyle,
1689
+ onScroll: scrollEvent
1690
+ }, [
1691
+ h('div', {
1692
+ class: 'vxe-select--y-space',
1693
+ style: {
1694
+ height: bodyHeight ? `${bodyHeight}px` : ''
1695
+ }
1696
+ }),
1697
+ h('div', {
1698
+ ref: refVirtualBody,
1699
+ class: 'vxe-tree--node-list-body',
1700
+ style: {
1701
+ transform: `translateY(${topSpaceHeight}px)`
1702
+ }
1703
+ }, renderList(treeList))
1704
+ ]),
1705
+ footerSlot
1706
+ ? h('div', {
1707
+ ref: refFooterWrapperElem,
1708
+ class: 'vxe-tree--footer-wrapper'
1709
+ }, footerSlot({ $tree: $xeTree }))
1710
+ : renderEmptyElement($xeTree),
1239
1711
  /**
1240
1712
  * 加载中
1241
1713
  */
@@ -1259,7 +1731,7 @@ export default defineVxeComponent({
1259
1731
  dataFlag.value++;
1260
1732
  });
1261
1733
  watch(dataFlag, () => {
1262
- loadTreeData(props.data || []);
1734
+ loadData(props.data || []);
1263
1735
  });
1264
1736
  watch(() => props.checkNodeKey, (val) => {
1265
1737
  reactData.selectRadioKey = val;
@@ -1274,13 +1746,52 @@ export default defineVxeComponent({
1274
1746
  watch(checkboxFlag, () => {
1275
1747
  updateCheckboxChecked(props.checkNodeKeys || []);
1276
1748
  });
1749
+ watch(() => props.filterValue, () => {
1750
+ triggerSearchEvent(new Event('filter'));
1751
+ });
1752
+ const hFlag = ref(0);
1753
+ watch(() => props.height, () => {
1754
+ hFlag.value++;
1755
+ });
1756
+ watch(() => props.minHeight, () => {
1757
+ hFlag.value++;
1758
+ });
1759
+ watch(() => props.maxHeight, () => {
1760
+ hFlag.value++;
1761
+ });
1762
+ watch(hFlag, () => {
1763
+ recalculate();
1764
+ });
1765
+ onMounted(() => {
1766
+ if (props.autoResize) {
1767
+ const el = refElem.value;
1768
+ const parentEl = getParentElem();
1769
+ const resizeObserver = globalResize.create(() => {
1770
+ if (props.autoResize) {
1771
+ recalculate();
1772
+ }
1773
+ });
1774
+ if (el) {
1775
+ resizeObserver.observe(el);
1776
+ }
1777
+ if (parentEl) {
1778
+ resizeObserver.observe(parentEl);
1779
+ }
1780
+ internalData.resizeObserver = resizeObserver;
1781
+ }
1782
+ globalEvents.on($xeTree, 'resize', handleGlobalResizeEvent);
1783
+ });
1277
1784
  onUnmounted(() => {
1278
- reactData.treeList = [];
1785
+ const { resizeObserver } = internalData;
1786
+ if (resizeObserver) {
1787
+ resizeObserver.disconnect();
1788
+ }
1279
1789
  internalData.treeExpandedMaps = {};
1280
1790
  internalData.indeterminateRowMaps = {};
1281
1791
  internalData.nodeMaps = {};
1792
+ globalEvents.off($xeTree, 'resize');
1282
1793
  });
1283
- loadTreeData(props.data || []);
1794
+ loadData(props.data || []);
1284
1795
  $xeTree.renderVN = renderVN;
1285
1796
  return $xeTree;
1286
1797
  },