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, PropType, computed, VNode, watch, onUnmounted, nextTick } from 'vue'
1
+ import { ref, h, reactive, PropType, computed, VNode, 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
  import type { TreeReactData, VxeTreeEmits, VxeTreePropTypes, TreeInternalData, TreePrivateRef, VxeTreeDefines, VxeTreePrivateComputed, TreePrivateMethods, TreeMethods, ValueOf, VxeTreeConstructor, VxeTreePrivateMethods } from '../../../types'
@@ -19,7 +21,15 @@ export default defineVxeComponent({
19
21
  name: 'VxeTree',
20
22
  props: {
21
23
  data: Array as PropType<VxeTreePropTypes.Data>,
24
+ autoResize: {
25
+ type: Boolean as PropType<VxeTreePropTypes.AutoResize>,
26
+ default: () => getConfig().tree.autoResize
27
+ },
22
28
  height: [String, Number] as PropType<VxeTreePropTypes.Height>,
29
+ maxHeight: {
30
+ type: [String, Number] as PropType<VxeTreePropTypes.MaxHeight>,
31
+ default: () => getConfig().tree.maxHeight
32
+ },
23
33
  minHeight: {
24
34
  type: [String, Number] as PropType<VxeTreePropTypes.MinHeight>,
25
35
  default: () => getConfig().tree.minHeight
@@ -111,10 +121,13 @@ export default defineVxeComponent({
111
121
  type: String as PropType<VxeTreePropTypes.IconLoaded>,
112
122
  default: () => getConfig().tree.iconLoaded
113
123
  },
124
+ filterValue: [String, Number] as PropType<VxeTreePropTypes.FilterValue>,
125
+ filterConfig: Object as PropType<VxeTreePropTypes.FilterConfig>,
114
126
  size: {
115
127
  type: String as PropType<VxeTreePropTypes.Size>,
116
128
  default: () => getConfig().tree.size || getConfig().size
117
- }
129
+ },
130
+ virtualYConfig: Object as PropType<VxeTreePropTypes.VirtualYConfig>
118
131
  },
119
132
  emits: [
120
133
  'update:modelValue',
@@ -126,7 +139,8 @@ export default defineVxeComponent({
126
139
  'radio-change',
127
140
  'checkbox-change',
128
141
  'load-success',
129
- 'load-error'
142
+ 'load-error',
143
+ 'scroll'
130
144
  ] as VxeTreeEmits,
131
145
  setup (props, context) {
132
146
  const { emit, slots } = context
@@ -136,9 +150,20 @@ export default defineVxeComponent({
136
150
  const { computeSize } = useSize(props)
137
151
 
138
152
  const refElem = ref<HTMLDivElement>()
153
+ const refHeaderWrapperElem = ref<HTMLDivElement>()
154
+ const refFooterWrapperElem = ref<HTMLDivElement>()
155
+ const refVirtualWrapper = ref<HTMLDivElement>()
156
+ const refVirtualBody = ref<HTMLDivElement>()
139
157
 
140
158
  const reactData = reactive<TreeReactData>({
159
+ parentHeight: 0,
160
+ customHeight: 0,
161
+ customMinHeight: 0,
162
+ customMaxHeight: 0,
141
163
  currentNode: null,
164
+ scrollYLoad: false,
165
+ bodyHeight: 0,
166
+ topSpaceHeight: 0,
142
167
  selectRadioKey: props.checkNodeKey,
143
168
  treeList: [],
144
169
  updateExpandedFlag: 1,
@@ -147,11 +172,28 @@ export default defineVxeComponent({
147
172
 
148
173
  const internalData: TreeInternalData = {
149
174
  // initialized: false,
175
+ // lastFilterValue: '',
176
+ treeFullData: [],
177
+ afterTreeList: [],
178
+ afterVisibleList: [],
150
179
  nodeMaps: {},
151
180
  selectCheckboxMaps: {},
152
181
  indeterminateRowMaps: {},
153
182
  treeExpandedMaps: {},
154
- treeExpandLazyLoadedMaps: {}
183
+ treeExpandLazyLoadedMaps: {},
184
+
185
+ lastScrollLeft: 0,
186
+ lastScrollTop: 0,
187
+ scrollYStore: {
188
+ startIndex: 0,
189
+ endIndex: 0,
190
+ visibleSize: 0,
191
+ offsetSize: 0,
192
+ rowHeight: 0
193
+ },
194
+
195
+ lastScrollTime: 0
196
+ // hpTimeout: undefined
155
197
  }
156
198
 
157
199
  const refMaps: TreePrivateRef = {
@@ -187,6 +229,10 @@ export default defineVxeComponent({
187
229
  return props.hasChildField || 'hasChild'
188
230
  })
189
231
 
232
+ const computeVirtualYOpts = computed(() => {
233
+ return Object.assign({} as { gt: number }, getConfig().tree.virtualYConfig, props.virtualYConfig)
234
+ })
235
+
190
236
  const computeIsRowCurrent = computed(() => {
191
237
  const nodeOpts = computeNodeOpts.value
192
238
  const { isCurrent } = nodeOpts
@@ -222,18 +268,27 @@ export default defineVxeComponent({
222
268
  })
223
269
 
224
270
  const computeTreeStyle = computed(() => {
225
- const { height, minHeight } = props
271
+ const { customHeight, customMinHeight, customMaxHeight } = reactData
226
272
  const stys: Record<string, string> = {}
227
- if (height) {
228
- stys.height = toCssUnit(height)
273
+ if (customHeight) {
274
+ stys.height = toCssUnit(customHeight)
229
275
  }
230
- if (minHeight) {
231
- stys.minHeight = toCssUnit(minHeight)
276
+ if (customMinHeight) {
277
+ stys.minHeight = toCssUnit(customMinHeight)
278
+ }
279
+ if (customMaxHeight) {
280
+ stys.maxHeight = toCssUnit(customMaxHeight)
232
281
  }
233
282
  return stys
234
283
  })
235
284
 
285
+ const computeFilterOpts = computed(() => {
286
+ return Object.assign({}, getConfig().tree.filterConfig, props.filterConfig)
287
+ })
288
+
236
289
  const computeMaps: VxeTreePrivateComputed = {
290
+ computeChildrenField,
291
+ computeMapChildrenField,
237
292
  computeRadioOpts,
238
293
  computeCheckboxOpts,
239
294
  computeNodeOpts
@@ -383,6 +438,41 @@ export default defineVxeComponent({
383
438
  emit(type, createEvent(evnt, { $tree: $xeTree }, params))
384
439
  }
385
440
 
441
+ const getParentElem = () => {
442
+ const el = refElem.value
443
+ return el ? el.parentElement : null
444
+ }
445
+
446
+ const calcTableHeight = (key: 'height' | 'minHeight' | 'maxHeight') => {
447
+ const { parentHeight } = reactData
448
+ const val = props[key]
449
+ let num = 0
450
+ if (val) {
451
+ if (val === '100%' || val === 'auto') {
452
+ num = parentHeight
453
+ } else {
454
+ if (isScale(val)) {
455
+ num = Math.floor((XEUtils.toInteger(val) || 1) / 100 * parentHeight)
456
+ } else {
457
+ num = XEUtils.toNumber(val)
458
+ }
459
+ num = Math.max(40, num)
460
+ }
461
+ }
462
+ return num
463
+ }
464
+
465
+ const updateHeight = () => {
466
+ reactData.customHeight = calcTableHeight('height')
467
+ reactData.customMinHeight = calcTableHeight('minHeight')
468
+ reactData.customMaxHeight = calcTableHeight('maxHeight')
469
+
470
+ // 如果启用虚拟滚动,默认高度
471
+ if (reactData.scrollYLoad && !(reactData.customHeight || reactData.customMinHeight)) {
472
+ reactData.customHeight = 300
473
+ }
474
+ }
475
+
386
476
  const createNode = (records: any[]) => {
387
477
  const valueField = computeValueField.value
388
478
  return Promise.resolve(
@@ -398,354 +488,383 @@ export default defineVxeComponent({
398
488
  )
399
489
  }
400
490
 
401
- const treeMethods: TreeMethods = {
402
- dispatchEvent,
403
- clearCurrentNode () {
404
- reactData.currentNode = null
405
- return nextTick()
406
- },
407
- getCurrentNodeId () {
408
- const { currentNode } = reactData
409
- if (currentNode) {
410
- return getNodeId(currentNode)
491
+ const cacheNodeMap = () => {
492
+ const { treeFullData } = internalData
493
+ const valueField = computeValueField.value
494
+ const childrenField = computeChildrenField.value
495
+ const keyMaps: Record<string, VxeTreeDefines.NodeCacheItem> = {}
496
+ XEUtils.eachTree(treeFullData, (item, index, items, path, parent, nodes) => {
497
+ let nodeid = getNodeId(item)
498
+ if (!nodeid) {
499
+ nodeid = getNodeUniqueId()
500
+ XEUtils.set(item, valueField, nodeid)
411
501
  }
412
- return null
413
- },
414
- getCurrentNode () {
415
- const { currentNode } = reactData
416
- const { nodeMaps } = internalData
417
- if (currentNode) {
418
- const nodeItem = nodeMaps[getNodeId(currentNode)]
419
- if (nodeItem) {
420
- return nodeItem.item
421
- }
502
+ keyMaps[nodeid] = {
503
+ item,
504
+ index,
505
+ items,
506
+ parent,
507
+ nodes,
508
+ level: nodes.length,
509
+ treeIndex: index,
510
+ lineCount: 0,
511
+ treeLoaded: false
422
512
  }
423
- return null
424
- },
425
- setCurrentNodeId (nodeKey) {
426
- const { nodeMaps } = internalData
427
- const nodeItem = nodeMaps[nodeKey]
428
- reactData.currentNode = nodeItem ? nodeItem.item : null
429
- return nextTick()
430
- },
431
- setCurrentNode (node) {
432
- reactData.currentNode = node
433
- return nextTick()
434
- },
435
- clearRadioNode () {
436
- reactData.selectRadioKey = null
437
- return nextTick()
438
- },
439
- getRadioNodeId () {
440
- return reactData.selectRadioKey || null
441
- },
442
- getRadioNode () {
443
- const { selectRadioKey } = reactData
444
- const { nodeMaps } = internalData
445
- if (selectRadioKey) {
446
- const nodeItem = nodeMaps[selectRadioKey]
447
- if (nodeItem) {
448
- return nodeItem.item
513
+ }, { children: childrenField })
514
+ internalData.nodeMaps = keyMaps
515
+ }
516
+
517
+ const updateAfterDataIndex = () => {
518
+ const { transform } = props
519
+ const { afterTreeList, nodeMaps } = internalData
520
+ const childrenField = computeChildrenField.value
521
+ const mapChildrenField = computeMapChildrenField.value
522
+ XEUtils.eachTree(afterTreeList, (item, index, items) => {
523
+ const nodeid = getNodeId(item)
524
+ const nodeItem = nodeMaps[nodeid]
525
+ if (nodeItem) {
526
+ nodeItem.items = items
527
+ nodeItem.treeIndex = index
528
+ } else {
529
+ const rest = {
530
+ item,
531
+ index,
532
+ items,
533
+ parent,
534
+ nodes: [],
535
+ level: 0,
536
+ treeIndex: index,
537
+ lineCount: 0,
538
+ treeLoaded: false
449
539
  }
540
+ nodeMaps[nodeid] = rest
450
541
  }
451
- return null
452
- },
453
- setRadioNodeId (nodeKey) {
454
- reactData.selectRadioKey = nodeKey
455
- return nextTick()
456
- },
457
- setRadioNode,
458
- setCheckboxNode,
459
- setCheckboxByNodeId,
460
- getCheckboxNodeIds () {
461
- const { selectCheckboxMaps } = internalData
462
- return Object.keys(selectCheckboxMaps)
463
- },
464
- getCheckboxNodes () {
465
- const { nodeMaps, selectCheckboxMaps } = internalData
466
- const list: any[] = []
467
- XEUtils.each(selectCheckboxMaps, (item, nodeid) => {
468
- const nodeItem = nodeMaps[nodeid]
469
- if (nodeItem) {
470
- list.push(nodeItem.item)
471
- }
472
- })
473
- return list
474
- },
475
- clearCheckboxNode () {
476
- internalData.selectCheckboxMaps = {}
477
- reactData.updateCheckboxFlag++
478
- return nextTick()
479
- },
480
- setAllCheckboxNode (checked) {
481
- const { transform } = props
482
- const selectMaps: Record<string, boolean> = {}
483
- const childrenField = computeChildrenField.value
484
- const mapChildrenField = computeMapChildrenField.value
485
- if (checked) {
486
- XEUtils.eachTree(reactData.treeList, (node) => {
487
- const nodeid = getNodeId(node)
488
- selectMaps[nodeid] = true
489
- }, { children: transform ? mapChildrenField : childrenField })
542
+ }, { children: transform ? mapChildrenField : childrenField })
543
+ }
544
+
545
+ const updateAfterFullData = () => {
546
+ const { transform, filterValue } = props
547
+ const { treeFullData, lastFilterValue } = internalData
548
+ const titleField = computeTitleField.value
549
+ const childrenField = computeChildrenField.value
550
+ const mapChildrenField = computeMapChildrenField.value
551
+ const filterOpts = computeFilterOpts.value
552
+ const { autoExpandAll, beforeFilterMethod, filterMethod, afterFilterMethod } = filterOpts
553
+ let fullList = treeFullData
554
+ let treeList = fullList
555
+ let filterStr = ''
556
+ if (filterValue || filterValue === 0) {
557
+ filterStr = `${filterValue}`
558
+ const handleSearch = filterMethod
559
+ ? (item: any) => {
560
+ return filterMethod({
561
+ $tree: $xeTree,
562
+ node: item,
563
+ filterValue: filterStr
564
+ })
565
+ }
566
+ : (item: any) => {
567
+ return String(item[titleField]).toLowerCase().indexOf(filterStr) > -1
568
+ }
569
+ const bafParams = { $tree: $xeTree, filterValue: filterStr }
570
+ if (beforeFilterMethod) {
571
+ beforeFilterMethod(bafParams)
490
572
  }
491
- internalData.selectCheckboxMaps = selectMaps
492
- reactData.updateCheckboxFlag++
493
- return nextTick()
494
- },
495
- clearExpandNode () {
496
- return treeMethods.clearAllExpandNode()
497
- },
498
- clearAllExpandNode () {
499
- const { nodeMaps } = internalData
500
- XEUtils.each(nodeMaps, (nodeItem: VxeTreeDefines.NodeCacheItem) => {
501
- nodeItem.treeLoaded = false
502
- })
503
- internalData.treeExpandedMaps = {}
504
- reactData.updateExpandedFlag++
505
- return nextTick()
506
- },
507
- setExpandByNodeId (nodeids, expanded) {
508
- const { treeExpandedMaps } = internalData
509
- if (nodeids) {
510
- if (!XEUtils.isArray(nodeids)) {
511
- nodeids = [nodeids]
512
- }
513
- nodeids.forEach((nodeid: string) => {
514
- handleSetExpand(nodeid, expanded, treeExpandedMaps)
515
- })
516
- reactData.updateExpandedFlag++
573
+ if (transform) {
574
+ treeList = XEUtils.searchTree(treeFullData, handleSearch, { children: childrenField, mapChildren: mapChildrenField, isEvery: true })
575
+ fullList = treeList
576
+ } else {
577
+ fullList = treeFullData.filter(handleSearch)
517
578
  }
518
- return nextTick()
519
- },
520
- getExpandNodeIds () {
521
- const { treeExpandedMaps } = internalData
522
- return XEUtils.keys(treeExpandedMaps)
523
- },
524
- getExpandNodes () {
525
- const { nodeMaps, treeExpandedMaps } = internalData
526
- const list: any[] = []
527
- XEUtils.each(treeExpandedMaps, (item, nodeid) => {
528
- const nodeItem = nodeMaps[nodeid]
529
- if (nodeItem) {
530
- list.push(nodeItem.item)
579
+ internalData.lastFilterValue = filterStr
580
+ nextTick(() => {
581
+ // 筛选时自动展开
582
+ if (autoExpandAll) {
583
+ $xeTree.setAllExpandNode(true).then(() => {
584
+ if (afterFilterMethod) {
585
+ afterFilterMethod(bafParams)
586
+ }
587
+ })
588
+ } else {
589
+ if (afterFilterMethod) {
590
+ afterFilterMethod(bafParams)
591
+ }
531
592
  }
532
593
  })
533
- return list
534
- },
535
- setExpandNode (nodes, expanded) {
536
- const { treeExpandedMaps } = internalData
537
- if (nodes) {
538
- if (!XEUtils.isArray(nodes)) {
539
- nodes = [nodes]
594
+ } else {
595
+ if (transform) {
596
+ treeList = XEUtils.searchTree(treeFullData, () => true, { children: childrenField, mapChildren: mapChildrenField, isEvery: true })
597
+ fullList = treeList
598
+ if (lastFilterValue) {
599
+ const bafParams = { $tree: $xeTree, filterValue: filterStr }
600
+ if (beforeFilterMethod) {
601
+ beforeFilterMethod(bafParams)
602
+ }
603
+ // 取消筛选时自动收起
604
+ nextTick(() => {
605
+ if (autoExpandAll) {
606
+ $xeTree.clearAllExpandNode().then(() => {
607
+ if (afterFilterMethod) {
608
+ afterFilterMethod(bafParams)
609
+ }
610
+ })
611
+ } else {
612
+ if (afterFilterMethod) {
613
+ afterFilterMethod(bafParams)
614
+ }
615
+ }
616
+ })
540
617
  }
541
- nodes.forEach((node: any) => {
542
- const nodeid = getNodeId(node)
543
- handleSetExpand(nodeid, expanded, treeExpandedMaps)
544
- })
545
- reactData.updateExpandedFlag++
546
618
  }
547
- return nextTick()
548
- },
549
- toggleExpandByNodeId (nodeids) {
550
- const { treeExpandedMaps } = internalData
551
- if (nodeids) {
552
- if (!XEUtils.isArray(nodeids)) {
553
- nodeids = [nodeids]
619
+ internalData.lastFilterValue = ''
620
+ }
621
+ internalData.afterVisibleList = fullList
622
+ internalData.afterTreeList = treeList
623
+ updateAfterDataIndex()
624
+ }
625
+
626
+ /**
627
+ * 如果为虚拟树、则将树结构拍平
628
+ */
629
+ const handleTreeToList = () => {
630
+ const { transform } = props
631
+ const { afterTreeList, treeExpandedMaps } = internalData
632
+ const mapChildrenField = computeMapChildrenField.value
633
+ const expandMaps: {
634
+ [key: string]: number
635
+ } = {}
636
+ if (transform) {
637
+ const fullData: any[] = []
638
+ XEUtils.eachTree(afterTreeList, (item, index, items, path, parentRow) => {
639
+ const nodeid = getNodeId(item)
640
+ const parentNodeid = getNodeId(parentRow)
641
+ if (!parentRow || (expandMaps[parentNodeid] && treeExpandedMaps[parentNodeid])) {
642
+ expandMaps[nodeid] = 1
643
+ fullData.push(item)
554
644
  }
555
- nodeids.forEach((nodeid: string) => {
556
- handleSetExpand(nodeid, !treeExpandedMaps[nodeid], treeExpandedMaps)
557
- })
558
- reactData.updateExpandedFlag++
645
+ }, { children: mapChildrenField })
646
+ updateScrollYStatus(fullData)
647
+ internalData.afterVisibleList = fullData
648
+ return fullData
649
+ }
650
+ return internalData.afterVisibleList
651
+ }
652
+
653
+ const handleData = (force?: boolean) => {
654
+ const { scrollYLoad } = reactData
655
+ const { scrollYStore } = internalData
656
+ let fullList: any[] = internalData.afterVisibleList
657
+ if (force) {
658
+ // 更新数据,处理筛选和排序
659
+ updateAfterFullData()
660
+ // 如果为虚拟树,将树结构拍平
661
+ fullList = handleTreeToList()
662
+ }
663
+ const treeList = scrollYLoad ? fullList.slice(scrollYStore.startIndex, scrollYStore.endIndex) : fullList.slice(0)
664
+ reactData.treeList = treeList
665
+ }
666
+
667
+ const triggerSearchEvent = XEUtils.debounce(() => handleData(true), 350, { trailing: true })
668
+
669
+ const loadData = (list: any[]) => {
670
+ const { expandAll, transform } = props
671
+ const { initialized, scrollYStore } = internalData
672
+ const keyField = computeKeyField.value
673
+ const parentField = computeParentField.value
674
+ const childrenField = computeChildrenField.value
675
+ const fullData = transform ? XEUtils.toArrayTree(list, { key: keyField, parentKey: parentField, mapChildren: childrenField }) : list ? list.slice(0) : []
676
+ internalData.treeFullData = fullData
677
+ Object.assign(scrollYStore, {
678
+ startIndex: 0,
679
+ endIndex: 1,
680
+ visibleSize: 0
681
+ })
682
+ const sYLoad = updateScrollYStatus(fullData)
683
+ cacheNodeMap()
684
+ handleData(true)
685
+ if (sYLoad) {
686
+ if (!(props.height || props.maxHeight)) {
687
+ errLog('vxe.error.reqProp', ['height | max-height | virtual-y-config.enabled=false'])
559
688
  }
560
- return nextTick()
561
- },
562
- toggleExpandNode (nodes) {
563
- const { treeExpandedMaps } = internalData
564
- if (nodes) {
565
- if (!XEUtils.isArray(nodes)) {
566
- nodes = [nodes]
689
+ }
690
+ return computeScrollLoad().then(() => {
691
+ if (!initialized) {
692
+ if (list && list.length) {
693
+ internalData.initialized = true
694
+ if (expandAll) {
695
+ $xeTree.setAllExpandNode(true)
696
+ }
697
+ $xeTree.setCheckboxByNodeId(props.checkNodeKeys || [], true)
567
698
  }
568
- nodes.forEach((node: any) => {
569
- const nodeid = getNodeId(node)
570
- handleSetExpand(nodeid, !treeExpandedMaps[nodeid], treeExpandedMaps)
571
- })
572
- reactData.updateExpandedFlag++
573
699
  }
574
- return nextTick()
575
- },
576
- setAllExpandNode (expanded) {
577
- const { transform } = props
578
- const { treeExpandedMaps } = internalData
579
- const childrenField = computeChildrenField.value
580
- const mapChildrenField = computeMapChildrenField.value
581
- if (expanded) {
582
- XEUtils.eachTree(reactData.treeList, (node) => {
583
- const childList: any[] = XEUtils.get(node, childrenField)
584
- const hasChild = childList && childList.length
585
- if (hasChild) {
586
- const nodeid = getNodeId(node)
587
- treeExpandedMaps[nodeid] = true
588
- }
589
- }, { children: transform ? mapChildrenField : childrenField })
590
- } else {
591
- internalData.treeExpandedMaps = {}
700
+ updateHeight()
701
+ refreshScroll()
702
+ })
703
+ }
704
+
705
+ const updateScrollYStatus = (fullData?: any[]) => {
706
+ const { transform } = props
707
+ const virtualYOpts = computeVirtualYOpts.value
708
+ const allList = fullData || internalData.treeFullData
709
+ // 如果gt为0,则总是启用
710
+ const scrollYLoad = !!transform && !!virtualYOpts.enabled && virtualYOpts.gt > -1 && (virtualYOpts.gt === 0 || virtualYOpts.gt < allList.length)
711
+ reactData.scrollYLoad = scrollYLoad
712
+ return scrollYLoad
713
+ }
714
+
715
+ const updateYSpace = () => {
716
+ const { scrollYLoad } = reactData
717
+ const { scrollYStore, afterVisibleList } = internalData
718
+ reactData.bodyHeight = scrollYLoad ? afterVisibleList.length * scrollYStore.rowHeight : 0
719
+ reactData.topSpaceHeight = scrollYLoad ? Math.max(scrollYStore.startIndex * scrollYStore.rowHeight, 0) : 0
720
+ }
721
+
722
+ const updateYData = () => {
723
+ handleData()
724
+ updateYSpace()
725
+ }
726
+
727
+ const computeScrollLoad = () => {
728
+ return nextTick().then(() => {
729
+ const { scrollYLoad } = reactData
730
+ const { scrollYStore } = internalData
731
+ const virtualBodyElem = refVirtualBody.value
732
+ const virtualYOpts = computeVirtualYOpts.value
733
+ let rowHeight = 0
734
+ let firstItemElem: HTMLElement | undefined
735
+ if (virtualBodyElem) {
736
+ if (!firstItemElem) {
737
+ firstItemElem = virtualBodyElem.children[0] as HTMLElement
738
+ }
592
739
  }
593
- reactData.updateExpandedFlag++
594
- return nextTick()
595
- },
596
- reloadExpandNode (node) {
597
- const { lazy } = props
598
- if (lazy) {
599
- treeMethods.clearExpandLoaded(node)
600
- return handleAsyncTreeExpandChilds(node)
740
+ if (firstItemElem) {
741
+ rowHeight = firstItemElem.offsetHeight
601
742
  }
602
- return nextTick()
603
- },
604
- clearExpandLoaded (node) {
605
- const { lazy } = props
606
- const { nodeMaps } = internalData
607
- if (lazy) {
608
- const nodeItem = nodeMaps[getNodeId(node)]
609
- if (nodeItem) {
610
- nodeItem.treeLoaded = false
611
- }
743
+ rowHeight = Math.max(20, rowHeight)
744
+ scrollYStore.rowHeight = rowHeight
745
+ // 计算 Y 逻辑
746
+ if (scrollYLoad) {
747
+ const scrollBodyElem = refVirtualWrapper.value
748
+ const visibleYSize = Math.max(8, scrollBodyElem ? Math.ceil(scrollBodyElem.clientHeight / rowHeight) : 0)
749
+ const offsetYSize = Math.max(0, Math.min(2, XEUtils.toNumber(virtualYOpts.oSize)))
750
+ scrollYStore.offsetSize = offsetYSize
751
+ scrollYStore.visibleSize = visibleYSize
752
+ scrollYStore.endIndex = Math.max(scrollYStore.startIndex, visibleYSize + offsetYSize, scrollYStore.endIndex)
753
+ updateYData()
754
+ } else {
755
+ updateYSpace()
612
756
  }
613
- return nextTick()
614
- },
615
- /**
616
- * 用于树结构,给行数据加载子节点
617
- */
618
- loadChildrenNode (node, childRecords) {
619
- const { lazy, transform } = props
620
- const { nodeMaps } = internalData
621
- if (!lazy) {
622
- return Promise.resolve([])
757
+ })
758
+ }
759
+
760
+ /**
761
+ * 如果有滚动条,则滚动到对应的位置
762
+ * @param {Number} scrollLeft 左距离
763
+ * @param {Number} scrollTop 上距离
764
+ */
765
+ const scrollTo = (scrollLeft: number | null, scrollTop?: number | null) => {
766
+ const scrollBodyElem = refVirtualWrapper.value
767
+ if (scrollBodyElem) {
768
+ if (XEUtils.isNumber(scrollLeft)) {
769
+ scrollBodyElem.scrollLeft = scrollLeft
623
770
  }
624
- const childrenField = computeChildrenField.value
625
- const parentNodeItem = nodeMaps[getNodeId(node)]
626
- const parentLevel = parentNodeItem ? parentNodeItem.level : 0
627
- const parentNodes = parentNodeItem ? parentNodeItem.nodes : []
628
- return createNode(childRecords).then((nodeList) => {
629
- XEUtils.eachTree(nodeList, (childRow, index, items, path, parent, nodes) => {
630
- const itemNodeId = getNodeId(childRow)
631
- nodeMaps[itemNodeId] = {
632
- item: node,
633
- itemIndex: -1,
634
- items,
635
- parent: parent || parentNodeItem.item,
636
- nodes: parentNodes.concat(nodes),
637
- level: parentLevel + nodes.length,
638
- lineCount: 0,
639
- treeLoaded: false
640
- }
641
- }, { children: childrenField })
642
- node[childrenField] = nodeList
643
- if (transform) {
644
- node[childrenField] = nodeList
645
- }
646
- updateNodeLine(node)
647
- return nodeList
648
- })
649
- },
650
- isExpandByNode,
651
- isCheckedByRadioNodeId,
652
- isCheckedByRadioNode,
653
- isCheckedByCheckboxNodeId,
654
- isIndeterminateByCheckboxNode,
655
- isCheckedByCheckboxNode,
656
- getCheckboxIndeterminateNodes () {
657
- const { nodeMaps, indeterminateRowMaps } = internalData
658
- const list: any[] = []
659
- XEUtils.each(indeterminateRowMaps, (item, nodeid) => {
660
- const nodeItem = nodeMaps[nodeid]
661
- if (nodeItem) {
662
- list.push(nodeItem.item)
663
- }
771
+ if (XEUtils.isNumber(scrollTop)) {
772
+ scrollBodyElem.scrollTop = scrollTop
773
+ }
774
+ }
775
+ if (reactData.scrollYLoad) {
776
+ return new Promise<void>(resolve => {
777
+ setTimeout(() => {
778
+ nextTick(() => {
779
+ resolve()
780
+ })
781
+ }, 50)
664
782
  })
665
- return list
666
783
  }
784
+ return nextTick()
667
785
  }
668
786
 
669
- const cacheNodeMap = () => {
670
- const { transform } = props
671
- const { treeList } = reactData
672
- const valueField = computeValueField.value
673
- const childrenField = computeChildrenField.value
674
- const mapChildrenField = computeMapChildrenField.value
675
- const keyMaps: Record<string, VxeTreeDefines.NodeCacheItem> = {}
676
- XEUtils.eachTree(treeList, (item, itemIndex, items, path, parent, nodes) => {
677
- let nodeid = getNodeId(item)
678
- if (!nodeid) {
679
- nodeid = getNodeUniqueId()
680
- XEUtils.set(item, valueField, nodeid)
681
- }
682
- keyMaps[nodeid] = {
683
- item,
684
- itemIndex,
685
- items,
686
- parent,
687
- nodes,
688
- level: nodes.length,
689
- lineCount: 0,
690
- treeLoaded: false
787
+ /**
788
+ * 刷新滚动条
789
+ */
790
+ const refreshScroll = () => {
791
+ const { lastScrollLeft, lastScrollTop } = internalData
792
+ return clearScroll().then(() => {
793
+ if (lastScrollLeft || lastScrollTop) {
794
+ internalData.lastScrollLeft = 0
795
+ internalData.lastScrollTop = 0
796
+ return scrollTo(lastScrollLeft, lastScrollTop)
691
797
  }
692
- }, { children: transform ? mapChildrenField : childrenField })
693
- internalData.nodeMaps = keyMaps
798
+ })
694
799
  }
695
800
 
696
- const loadTreeData = (list: any[]) => {
697
- const { expandAll, transform } = props
698
- const { initialized } = internalData
699
- const keyField = computeKeyField.value
700
- const parentField = computeParentField.value
701
- const mapChildrenField = computeMapChildrenField.value
702
- if (transform) {
703
- reactData.treeList = XEUtils.toArrayTree(list, { key: keyField, parentKey: parentField, mapChildren: mapChildrenField })
704
- } else {
705
- reactData.treeList = list ? list.slice(0) : []
801
+ /**
802
+ * 重新计算列表
803
+ */
804
+ const recalculate = () => {
805
+ const { scrollYStore } = internalData
806
+ const { rowHeight } = scrollYStore
807
+ const el = refElem.value
808
+ if (el && el.clientWidth && el.clientHeight) {
809
+ const parentEl = getParentElem()
810
+ const headerWrapperEl = refHeaderWrapperElem.value
811
+ const footerWrapperEl = refFooterWrapperElem.value
812
+ const headHeight = headerWrapperEl ? headerWrapperEl.clientHeight : 0
813
+ const footHeight = footerWrapperEl ? footerWrapperEl.clientHeight : 0
814
+ if (parentEl) {
815
+ const parentPaddingSize = getPaddingTopBottomSize(parentEl)
816
+ reactData.parentHeight = Math.max(headHeight + footHeight + rowHeight, parentEl.clientHeight - parentPaddingSize - headHeight - footHeight)
817
+ }
818
+ updateHeight()
819
+ return computeScrollLoad().then(() => {
820
+ updateHeight()
821
+ updateYSpace()
822
+ })
706
823
  }
707
- cacheNodeMap()
708
- if (!initialized) {
709
- if (list && list.length) {
710
- internalData.initialized = true
711
- if (expandAll) {
712
- $xeTree.setAllExpandNode(true)
713
- }
714
- $xeTree.setCheckboxByNodeId(props.checkNodeKeys || [], true)
824
+ return nextTick()
825
+ }
826
+
827
+ const loadYData = (evnt: Event) => {
828
+ const { scrollYStore } = internalData
829
+ const { startIndex, endIndex, visibleSize, offsetSize, rowHeight } = scrollYStore
830
+ const scrollBodyElem = evnt.target as HTMLDivElement
831
+ const scrollTop = scrollBodyElem.scrollTop
832
+ const toVisibleIndex = Math.floor(scrollTop / rowHeight)
833
+ const offsetStartIndex = Math.max(0, toVisibleIndex - 1 - offsetSize)
834
+ const offsetEndIndex = toVisibleIndex + visibleSize + offsetSize
835
+ if (toVisibleIndex <= startIndex || toVisibleIndex >= endIndex - visibleSize - 1) {
836
+ if (startIndex !== offsetStartIndex || endIndex !== offsetEndIndex) {
837
+ scrollYStore.startIndex = offsetStartIndex
838
+ scrollYStore.endIndex = offsetEndIndex
839
+ updateYData()
715
840
  }
716
841
  }
717
842
  }
718
843
 
719
- const handleCountLine = (item: any, isRoot: boolean, nodeItem: VxeTreeDefines.NodeCacheItem) => {
720
- const { treeExpandedMaps } = internalData
721
- const childrenField = computeChildrenField.value
722
- const nodeid = getNodeId(item)
723
- nodeItem.lineCount++
724
- if (treeExpandedMaps[nodeid]) {
725
- XEUtils.arrayEach(item[childrenField], (childItem, childIndex, childList) => {
726
- if (!isRoot || childIndex < childList.length - 1) {
727
- handleCountLine(childItem, false, nodeItem)
728
- }
729
- })
844
+ const scrollEvent = (evnt: Event) => {
845
+ const scrollBodyElem = evnt.target as HTMLDivElement
846
+ const scrollTop = scrollBodyElem.scrollTop
847
+ const scrollLeft = scrollBodyElem.scrollLeft
848
+ const isX = scrollLeft !== internalData.lastScrollLeft
849
+ const isY = scrollTop !== internalData.lastScrollTop
850
+ internalData.lastScrollTop = scrollTop
851
+ internalData.lastScrollLeft = scrollLeft
852
+ if (reactData.scrollYLoad) {
853
+ loadYData(evnt)
730
854
  }
855
+ internalData.lastScrollTime = Date.now()
856
+ dispatchEvent('scroll', { scrollLeft, scrollTop, isX, isY }, evnt)
731
857
  }
732
858
 
733
- const updateNodeLine = (node: any) => {
734
- const { nodeMaps } = internalData
735
- if (node) {
736
- const nodeid = getNodeId(node)
737
- const nodeItem = nodeMaps[nodeid]
738
- if (nodeItem) {
739
- XEUtils.lastArrayEach(nodeItem.nodes, childItem => {
740
- const nodeid = getNodeId(childItem)
741
- const nodeItem = nodeMaps[nodeid]
742
- if (nodeItem) {
743
- nodeItem.lineCount = 0
744
- handleCountLine(childItem, true, nodeItem)
745
- }
746
- })
747
- }
859
+ const clearScroll = () => {
860
+ const scrollBodyElem = refVirtualWrapper.value
861
+ if (scrollBodyElem) {
862
+ scrollBodyElem.scrollTop = 0
863
+ scrollBodyElem.scrollLeft = 0
748
864
  }
865
+ internalData.lastScrollTop = 0
866
+ internalData.lastScrollLeft = 0
867
+ return nextTick()
749
868
  }
750
869
 
751
870
  const handleNodeClickEvent = (evnt: MouseEvent, node: any) => {
@@ -782,11 +901,11 @@ export default defineVxeComponent({
782
901
  dispatchEvent('node-dblclick', { node }, evnt)
783
902
  }
784
903
 
785
- const handleAsyncTreeExpandChilds = (node: any): Promise<void> => {
904
+ const handleAsyncTreeExpandChilds = (node: any) => {
786
905
  const checkboxOpts = computeCheckboxOpts.value
787
906
  const { loadMethod } = props
788
907
  const { checkStrictly } = checkboxOpts
789
- return new Promise(resolve => {
908
+ return new Promise<void>(resolve => {
790
909
  if (loadMethod) {
791
910
  const { nodeMaps } = internalData
792
911
  const nodeid = getNodeId(node)
@@ -814,12 +933,10 @@ export default defineVxeComponent({
814
933
  if (!checkStrictly && $xeTree.isCheckedByCheckboxNodeId(nodeid)) {
815
934
  handleCheckedCheckboxNode(childRows, true)
816
935
  }
817
- updateNodeLine(node)
818
936
  dispatchEvent('load-success', { node, data: childRecords }, new Event('load-success'))
819
937
  return nextTick()
820
938
  })
821
939
  } else {
822
- updateNodeLine(node)
823
940
  dispatchEvent('load-success', { node, data: childRecords }, new Event('load-success'))
824
941
  }
825
942
  }).catch((e) => {
@@ -828,10 +945,11 @@ export default defineVxeComponent({
828
945
  if (treeExpandLazyLoadedMaps[nodeid]) {
829
946
  treeExpandLazyLoadedMaps[nodeid] = false
830
947
  }
831
- updateNodeLine(node)
832
948
  dispatchEvent('load-error', { node, data: e }, new Event('load-error'))
833
949
  }).finally(() => {
834
- return nextTick()
950
+ handleTreeToList()
951
+ handleData()
952
+ return recalculate()
835
953
  })
836
954
  } else {
837
955
  resolve()
@@ -895,8 +1013,9 @@ export default defineVxeComponent({
895
1013
  })
896
1014
  }
897
1015
  reactData.updateExpandedFlag++
898
- expandNodes.forEach(updateNodeLine)
899
- return Promise.all(result)
1016
+ handleTreeToList()
1017
+ handleData()
1018
+ return Promise.all(result).then(() => recalculate())
900
1019
  }
901
1020
 
902
1021
  const toggleExpandEvent = (evnt: MouseEvent, node: any) => {
@@ -912,8 +1031,7 @@ export default defineVxeComponent({
912
1031
 
913
1032
  const updateCheckboxStatus = () => {
914
1033
  const { transform } = props
915
- const { treeList } = reactData
916
- const { selectCheckboxMaps, indeterminateRowMaps } = internalData
1034
+ const { selectCheckboxMaps, indeterminateRowMaps, afterTreeList } = internalData
917
1035
  const childrenField = computeChildrenField.value
918
1036
  const mapChildrenField = computeMapChildrenField.value
919
1037
  const checkboxOpts = computeCheckboxOpts.value
@@ -921,7 +1039,7 @@ export default defineVxeComponent({
921
1039
  if (!checkStrictly) {
922
1040
  const childRowMaps: Record<string, number> = {}
923
1041
  const childRowList: any[][] = []
924
- XEUtils.eachTree(treeList, (node) => {
1042
+ XEUtils.eachTree(afterTreeList, (node) => {
925
1043
  const nodeid = getNodeId(node)
926
1044
  const childList = node[childrenField]
927
1045
  if (childList && childList.length && !childRowMaps[nodeid]) {
@@ -936,13 +1054,14 @@ export default defineVxeComponent({
936
1054
  const childList: any[] = vals[2]
937
1055
  let sLen = 0 // 已选
938
1056
  let hLen = 0 // 半选
939
- let vLen = 0 // 有效行
1057
+ let vLen = 0 // 有效子行
1058
+ const cLen = childList.length // 子行
940
1059
  childList.forEach(
941
1060
  checkMethod
942
1061
  ? (item) => {
943
1062
  const childNodeid = getNodeId(item)
944
1063
  const isSelect = selectCheckboxMaps[childNodeid]
945
- if (checkMethod({ node: item })) {
1064
+ if (checkMethod({ $tree: $xeTree, node: item })) {
946
1065
  if (isSelect) {
947
1066
  sLen++
948
1067
  } else if (indeterminateRowMaps[childNodeid]) {
@@ -968,8 +1087,27 @@ export default defineVxeComponent({
968
1087
  vLen++
969
1088
  }
970
1089
  )
971
- const isSelected = sLen >= vLen
972
- const halfSelect = !isSelected && (sLen >= 1 || hLen >= 1)
1090
+
1091
+ let isSelected = false
1092
+ if (cLen > 0) {
1093
+ if (vLen > 0) {
1094
+ isSelected = (sLen > 0 || hLen > 0) && sLen >= vLen
1095
+ } else {
1096
+ // 如果存在子项禁用
1097
+ if ((sLen > 0 && sLen >= vLen)) {
1098
+ isSelected = true
1099
+ } else if (selectCheckboxMaps[nodeid]) {
1100
+ isSelected = true
1101
+ } else {
1102
+ isSelected = false
1103
+ }
1104
+ }
1105
+ } else {
1106
+ // 如果无子项
1107
+ isSelected = selectCheckboxMaps[nodeid]
1108
+ }
1109
+ const halfSelect = !isSelected && (sLen > 0 || hLen > 0)
1110
+
973
1111
  if (isSelected) {
974
1112
  selectCheckboxMaps[nodeid] = node
975
1113
  if (indeterminateRowMaps[nodeid]) {
@@ -1003,7 +1141,7 @@ export default defineVxeComponent({
1003
1141
  const { checkStrictly, checkMethod } = checkboxOpts
1004
1142
  let isDisabled = !!checkMethod
1005
1143
  if (checkMethod) {
1006
- isDisabled = !checkMethod({ node })
1144
+ isDisabled = !checkMethod({ $tree: $xeTree, node })
1007
1145
  }
1008
1146
  if (isDisabled) {
1009
1147
  return
@@ -1017,7 +1155,7 @@ export default defineVxeComponent({
1017
1155
  selectCheckboxMaps[nodeid] = node
1018
1156
  }
1019
1157
  if (!checkStrictly) {
1020
- XEUtils.eachTree(XEUtils.get(node, childrenField), (childNode) => {
1158
+ XEUtils.eachTree(XEUtils.get(node, transform ? mapChildrenField : childrenField), (childNode) => {
1021
1159
  const childNodeid = getNodeId(childNode)
1022
1160
  if (isChecked) {
1023
1161
  if (!selectCheckboxMaps[childNodeid]) {
@@ -1072,7 +1210,7 @@ export default defineVxeComponent({
1072
1210
  const { checkMethod } = radioOpts
1073
1211
  let isDisabled = !!checkMethod
1074
1212
  if (checkMethod) {
1075
- isDisabled = !checkMethod({ node })
1213
+ isDisabled = !checkMethod({ $tree: $xeTree, node })
1076
1214
  }
1077
1215
  if (isDisabled) {
1078
1216
  return
@@ -1084,6 +1222,315 @@ export default defineVxeComponent({
1084
1222
  dispatchEvent('radio-change', { node, value, checked: isChecked }, evnt)
1085
1223
  }
1086
1224
 
1225
+ const handleGlobalResizeEvent = () => {
1226
+ const el = refElem.value
1227
+ if (!el || !el.clientWidth) {
1228
+ return
1229
+ }
1230
+ recalculate()
1231
+ }
1232
+
1233
+ const treeMethods: TreeMethods = {
1234
+ dispatchEvent,
1235
+ getNodeId,
1236
+ loadData (data) {
1237
+ return loadData(data || [])
1238
+ },
1239
+ reloadData (data) {
1240
+ return loadData(data || [])
1241
+ },
1242
+ clearCurrentNode () {
1243
+ reactData.currentNode = null
1244
+ return nextTick()
1245
+ },
1246
+ getCurrentNodeId () {
1247
+ const { currentNode } = reactData
1248
+ if (currentNode) {
1249
+ return getNodeId(currentNode)
1250
+ }
1251
+ return null
1252
+ },
1253
+ getCurrentNode () {
1254
+ const { currentNode } = reactData
1255
+ const { nodeMaps } = internalData
1256
+ if (currentNode) {
1257
+ const nodeItem = nodeMaps[getNodeId(currentNode)]
1258
+ if (nodeItem) {
1259
+ return nodeItem.item
1260
+ }
1261
+ }
1262
+ return null
1263
+ },
1264
+ setCurrentNodeId (nodeKey) {
1265
+ const { nodeMaps } = internalData
1266
+ const nodeItem = nodeMaps[nodeKey]
1267
+ reactData.currentNode = nodeItem ? nodeItem.item : null
1268
+ return nextTick()
1269
+ },
1270
+ setCurrentNode (node) {
1271
+ reactData.currentNode = node
1272
+ return nextTick()
1273
+ },
1274
+ clearRadioNode () {
1275
+ reactData.selectRadioKey = null
1276
+ return nextTick()
1277
+ },
1278
+ getRadioNodeId () {
1279
+ return reactData.selectRadioKey || null
1280
+ },
1281
+ getRadioNode () {
1282
+ const { selectRadioKey } = reactData
1283
+ const { nodeMaps } = internalData
1284
+ if (selectRadioKey) {
1285
+ const nodeItem = nodeMaps[selectRadioKey]
1286
+ if (nodeItem) {
1287
+ return nodeItem.item
1288
+ }
1289
+ }
1290
+ return null
1291
+ },
1292
+ setRadioNodeId (nodeKey) {
1293
+ reactData.selectRadioKey = nodeKey
1294
+ return nextTick()
1295
+ },
1296
+ setRadioNode,
1297
+ setCheckboxNode,
1298
+ setCheckboxByNodeId,
1299
+ getCheckboxNodeIds () {
1300
+ const { selectCheckboxMaps } = internalData
1301
+ return Object.keys(selectCheckboxMaps)
1302
+ },
1303
+ getCheckboxNodes () {
1304
+ const { nodeMaps, selectCheckboxMaps } = internalData
1305
+ const list: any[] = []
1306
+ XEUtils.each(selectCheckboxMaps, (item, nodeid) => {
1307
+ const nodeItem = nodeMaps[nodeid]
1308
+ if (nodeItem) {
1309
+ list.push(nodeItem.item)
1310
+ }
1311
+ })
1312
+ return list
1313
+ },
1314
+ clearCheckboxNode () {
1315
+ internalData.selectCheckboxMaps = {}
1316
+ reactData.updateCheckboxFlag++
1317
+ return nextTick().then(() => {
1318
+ return { checkNodeKeys: [] }
1319
+ })
1320
+ },
1321
+ setAllCheckboxNode (checked) {
1322
+ const { transform } = props
1323
+ const selectMaps: Record<string, boolean> = {}
1324
+ const childrenField = computeChildrenField.value
1325
+ const mapChildrenField = computeMapChildrenField.value
1326
+ const checkKeys: string[] = []
1327
+ if (checked) {
1328
+ XEUtils.eachTree(internalData.afterTreeList, (node) => {
1329
+ const nodeid = getNodeId(node)
1330
+ checkKeys.push(nodeid)
1331
+ selectMaps[nodeid] = true
1332
+ }, { children: transform ? mapChildrenField : childrenField })
1333
+ }
1334
+ internalData.selectCheckboxMaps = selectMaps
1335
+ reactData.updateCheckboxFlag++
1336
+ return nextTick().then(() => {
1337
+ return { checkNodeKeys: checkKeys }
1338
+ })
1339
+ },
1340
+ clearExpandNode () {
1341
+ return treeMethods.clearAllExpandNode()
1342
+ },
1343
+ clearAllExpandNode () {
1344
+ const { nodeMaps, scrollYStore } = internalData
1345
+ XEUtils.each(nodeMaps, (nodeItem: VxeTreeDefines.NodeCacheItem) => {
1346
+ nodeItem.treeLoaded = false
1347
+ })
1348
+ internalData.treeExpandedMaps = {}
1349
+ reactData.updateExpandedFlag++
1350
+ reactData.topSpaceHeight = 0
1351
+ scrollYStore.startIndex = 0
1352
+ scrollYStore.endIndex = 1
1353
+ handleTreeToList()
1354
+ handleData()
1355
+ return recalculate()
1356
+ },
1357
+ setExpandByNodeId (nodeids, expanded) {
1358
+ const { treeExpandedMaps } = internalData
1359
+ if (nodeids) {
1360
+ if (!XEUtils.isArray(nodeids)) {
1361
+ nodeids = [nodeids]
1362
+ }
1363
+ nodeids.forEach((nodeid: string) => {
1364
+ handleSetExpand(nodeid, expanded, treeExpandedMaps)
1365
+ })
1366
+ reactData.updateExpandedFlag++
1367
+ }
1368
+ handleTreeToList()
1369
+ handleData()
1370
+ return recalculate()
1371
+ },
1372
+ getExpandNodeIds () {
1373
+ const { treeExpandedMaps } = internalData
1374
+ return XEUtils.keys(treeExpandedMaps)
1375
+ },
1376
+ getExpandNodes () {
1377
+ const { nodeMaps, treeExpandedMaps } = internalData
1378
+ const list: any[] = []
1379
+ XEUtils.each(treeExpandedMaps, (item, nodeid) => {
1380
+ const nodeItem = nodeMaps[nodeid]
1381
+ if (nodeItem) {
1382
+ list.push(nodeItem.item)
1383
+ }
1384
+ })
1385
+ return list
1386
+ },
1387
+ setExpandNode (nodes, expanded) {
1388
+ const { treeExpandedMaps } = internalData
1389
+ if (nodes) {
1390
+ if (!XEUtils.isArray(nodes)) {
1391
+ nodes = [nodes]
1392
+ }
1393
+ nodes.forEach((node: any) => {
1394
+ const nodeid = getNodeId(node)
1395
+ handleSetExpand(nodeid, expanded, treeExpandedMaps)
1396
+ })
1397
+ reactData.updateExpandedFlag++
1398
+ }
1399
+ handleTreeToList()
1400
+ handleData()
1401
+ return recalculate()
1402
+ },
1403
+ toggleExpandByNodeId (nodeids) {
1404
+ const { treeExpandedMaps } = internalData
1405
+ if (nodeids) {
1406
+ if (!XEUtils.isArray(nodeids)) {
1407
+ nodeids = [nodeids]
1408
+ }
1409
+ nodeids.forEach((nodeid: string) => {
1410
+ handleSetExpand(nodeid, !treeExpandedMaps[nodeid], treeExpandedMaps)
1411
+ })
1412
+ reactData.updateExpandedFlag++
1413
+ }
1414
+ handleTreeToList()
1415
+ handleData()
1416
+ return recalculate()
1417
+ },
1418
+ toggleExpandNode (nodes) {
1419
+ const { treeExpandedMaps } = internalData
1420
+ if (nodes) {
1421
+ if (!XEUtils.isArray(nodes)) {
1422
+ nodes = [nodes]
1423
+ }
1424
+ nodes.forEach((node: any) => {
1425
+ const nodeid = getNodeId(node)
1426
+ handleSetExpand(nodeid, !treeExpandedMaps[nodeid], treeExpandedMaps)
1427
+ })
1428
+ reactData.updateExpandedFlag++
1429
+ }
1430
+ handleTreeToList()
1431
+ handleData()
1432
+ return recalculate()
1433
+ },
1434
+ setAllExpandNode (expanded) {
1435
+ const { transform } = props
1436
+ const { treeExpandedMaps } = internalData
1437
+ const childrenField = computeChildrenField.value
1438
+ const mapChildrenField = computeMapChildrenField.value
1439
+ if (expanded) {
1440
+ XEUtils.eachTree(internalData.afterTreeList, (node) => {
1441
+ const childList: any[] = XEUtils.get(node, childrenField)
1442
+ const hasChild = childList && childList.length
1443
+ if (hasChild) {
1444
+ const nodeid = getNodeId(node)
1445
+ treeExpandedMaps[nodeid] = true
1446
+ }
1447
+ }, { children: transform ? mapChildrenField : childrenField })
1448
+ } else {
1449
+ internalData.treeExpandedMaps = {}
1450
+ }
1451
+ reactData.updateExpandedFlag++
1452
+ handleTreeToList()
1453
+ handleData()
1454
+ return recalculate()
1455
+ },
1456
+ reloadExpandNode (node) {
1457
+ const { lazy } = props
1458
+ if (lazy) {
1459
+ treeMethods.clearExpandLoaded(node)
1460
+ return handleAsyncTreeExpandChilds(node)
1461
+ }
1462
+ return recalculate()
1463
+ },
1464
+ clearExpandLoaded (node) {
1465
+ const { lazy } = props
1466
+ const { nodeMaps } = internalData
1467
+ if (lazy) {
1468
+ const nodeItem = nodeMaps[getNodeId(node)]
1469
+ if (nodeItem) {
1470
+ nodeItem.treeLoaded = false
1471
+ }
1472
+ }
1473
+ return recalculate()
1474
+ },
1475
+ /**
1476
+ * 用于树结构,给行数据加载子节点
1477
+ */
1478
+ loadChildrenNode (node, childRecords) {
1479
+ const { lazy, transform } = props
1480
+ const { nodeMaps } = internalData
1481
+ if (!lazy) {
1482
+ return Promise.resolve([])
1483
+ }
1484
+ const childrenField = computeChildrenField.value
1485
+ const mapChildrenField = computeMapChildrenField.value
1486
+ const parentNodeItem = nodeMaps[getNodeId(node)]
1487
+ const parentLevel = parentNodeItem ? parentNodeItem.level : 0
1488
+ const parentNodes = parentNodeItem ? parentNodeItem.nodes : []
1489
+ return createNode(childRecords).then((nodeList) => {
1490
+ XEUtils.eachTree(nodeList, (childRow, index, items, path, parent, nodes) => {
1491
+ const itemNodeId = getNodeId(childRow)
1492
+ nodeMaps[itemNodeId] = {
1493
+ item: node,
1494
+ index: -1,
1495
+ items,
1496
+ parent: parent || parentNodeItem.item,
1497
+ nodes: parentNodes.concat(nodes),
1498
+ level: parentLevel + nodes.length,
1499
+ treeIndex: -1,
1500
+ lineCount: 0,
1501
+ treeLoaded: false
1502
+ }
1503
+ }, { children: childrenField })
1504
+ node[childrenField] = nodeList
1505
+ if (transform) {
1506
+ node[mapChildrenField] = nodeList
1507
+ }
1508
+ updateAfterDataIndex()
1509
+ return nodeList
1510
+ })
1511
+ },
1512
+ isExpandByNode,
1513
+ isCheckedByRadioNodeId,
1514
+ isCheckedByRadioNode,
1515
+ isCheckedByCheckboxNodeId,
1516
+ isIndeterminateByCheckboxNode,
1517
+ isCheckedByCheckboxNode,
1518
+ getCheckboxIndeterminateNodes () {
1519
+ const { nodeMaps, indeterminateRowMaps } = internalData
1520
+ const list: any[] = []
1521
+ XEUtils.each(indeterminateRowMaps, (item, nodeid) => {
1522
+ const nodeItem = nodeMaps[nodeid]
1523
+ if (nodeItem) {
1524
+ list.push(nodeItem.item)
1525
+ }
1526
+ })
1527
+ return list
1528
+ },
1529
+ recalculate,
1530
+ scrollTo,
1531
+ clearScroll
1532
+ }
1533
+
1087
1534
  const treePrivateMethods: TreePrivateMethods = {
1088
1535
  }
1089
1536
 
@@ -1093,11 +1540,11 @@ export default defineVxeComponent({
1093
1540
  const { showRadio } = props
1094
1541
  const radioOpts = computeRadioOpts.value
1095
1542
  const { showIcon, checkMethod, visibleMethod } = radioOpts
1096
- const isVisible = !visibleMethod || visibleMethod({ node })
1543
+ const isVisible = !visibleMethod || visibleMethod({ $tree: $xeTree, node })
1097
1544
  let isDisabled = !!checkMethod
1098
1545
  if (showRadio && showIcon && isVisible) {
1099
1546
  if (checkMethod) {
1100
- isDisabled = !checkMethod({ node })
1547
+ isDisabled = !checkMethod({ $tree: $xeTree, node })
1101
1548
  }
1102
1549
  return h('div', {
1103
1550
  class: ['vxe-tree--radio-option', {
@@ -1123,11 +1570,11 @@ export default defineVxeComponent({
1123
1570
  const checkboxOpts = computeCheckboxOpts.value
1124
1571
  const { showIcon, checkMethod, visibleMethod } = checkboxOpts
1125
1572
  const isIndeterminate = isIndeterminateByCheckboxNodeid(nodeid)
1126
- const isVisible = !visibleMethod || visibleMethod({ node })
1573
+ const isVisible = !visibleMethod || visibleMethod({ $tree: $xeTree, node })
1127
1574
  let isDisabled = !!checkMethod
1128
1575
  if (showCheckbox && showIcon && isVisible) {
1129
1576
  if (checkMethod) {
1130
- isDisabled = !checkMethod({ node })
1577
+ isDisabled = !checkMethod({ $tree: $xeTree, node })
1131
1578
  }
1132
1579
  return h('div', {
1133
1580
  class: ['vxe-tree--checkbox-option', {
@@ -1149,10 +1596,10 @@ export default defineVxeComponent({
1149
1596
  return renderEmptyElement($xeTree)
1150
1597
  }
1151
1598
 
1152
- const renderNode = (node: any): VNode => {
1599
+ const renderNode = (node: any, nodeid: string) => {
1153
1600
  const { lazy, showRadio, showCheckbox, showLine, indent, iconOpen, iconClose, iconLoaded, showIcon } = props
1154
1601
  const { currentNode, selectRadioKey, updateExpandedFlag } = reactData
1155
- const { nodeMaps, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData
1602
+ const { afterTreeList, nodeMaps, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData
1156
1603
  const childrenField = computeChildrenField.value
1157
1604
  const titleField = computeTitleField.value
1158
1605
  const hasChildField = computeHasChildField.value
@@ -1161,33 +1608,14 @@ export default defineVxeComponent({
1161
1608
  const iconSlot = slots.icon
1162
1609
  const titleSlot = slots.title
1163
1610
  const extraSlot = slots.extra
1164
- const nodeid = getNodeId(node)
1165
1611
  const isExpand = updateExpandedFlag && treeExpandedMaps[nodeid]
1166
1612
  const nodeItem = nodeMaps[nodeid]
1167
1613
  const nodeValue = XEUtils.get(node, titleField)
1168
- const childVns: VNode[] = []
1169
- if (hasChild && treeExpandedMaps[nodeid]) {
1170
- if (showLine) {
1171
- childVns.push(
1172
- h('div', {
1173
- key: 'line',
1174
- class: 'vxe-tree--node-child-line',
1175
- style: {
1176
- height: `calc(${nodeItem.lineCount} * var(--vxe-ui-tree-node-height) - var(--vxe-ui-tree-node-height) / 2)`,
1177
- left: `${(nodeItem.level + 1) * (indent || 1)}px`
1178
- }
1179
- })
1180
- )
1181
- }
1182
- childList.forEach(childItem => {
1183
- childVns.push(renderNode(childItem))
1184
- })
1185
- }
1614
+ const nLevel = nodeItem.level
1186
1615
 
1187
1616
  let isRadioChecked = false
1188
1617
  if (showRadio) {
1189
- // eslint-disable-next-line eqeqeq
1190
- isRadioChecked = nodeid == selectRadioKey
1618
+ isRadioChecked = nodeid === String(selectRadioKey)
1191
1619
  }
1192
1620
 
1193
1621
  let isCheckboxChecked = false
@@ -1203,9 +1631,12 @@ export default defineVxeComponent({
1203
1631
  hasLazyChilds = node[hasChildField]
1204
1632
  isLazyLoaded = !!nodeItem.treeLoaded
1205
1633
  }
1634
+ const prevNode = nodeItem.items[nodeItem.treeIndex - 1]
1635
+ const nParams = { node, isExpand }
1206
1636
 
1207
1637
  return h('div', {
1208
- class: ['vxe-tree--node-wrapper', `node--level-${nodeItem.level}`],
1638
+ key: nodeid,
1639
+ class: ['vxe-tree--node-wrapper', `node--level-${nLevel}`],
1209
1640
  nodeid
1210
1641
  }, [
1211
1642
  h('div', {
@@ -1215,7 +1646,7 @@ export default defineVxeComponent({
1215
1646
  'is-checkbox--checked': isCheckboxChecked
1216
1647
  }],
1217
1648
  style: {
1218
- paddingLeft: `${(nodeItem.level - 1) * (indent || 1)}px`
1649
+ paddingLeft: `${(nLevel - 1) * (indent || 1)}px`
1219
1650
  },
1220
1651
  onClick (evnt) {
1221
1652
  handleNodeClickEvent(evnt, node)
@@ -1224,26 +1655,36 @@ export default defineVxeComponent({
1224
1655
  handleNodeDblclickEvent(evnt, node)
1225
1656
  }
1226
1657
  }, [
1227
- showIcon || showLine
1658
+ showLine
1228
1659
  ? h('div', {
1229
- class: 'vxe-tree--node-item-switcher'
1230
- }, showIcon && (lazy ? (isLazyLoaded ? hasChild : hasLazyChilds) : hasChild)
1231
- ? [
1232
- h('div', {
1233
- class: 'vxe-tree--node-item-icon',
1234
- onClick (evnt) {
1235
- toggleExpandEvent(evnt, node)
1236
- }
1237
- }, iconSlot
1238
- ? iconSlot({ node, isExpand })
1239
- : [
1240
- h('i', {
1241
- class: isLazyLoading ? (iconLoaded || getIcon().TREE_NODE_LOADED) : (isExpand ? (iconOpen || getIcon().TREE_NODE_OPEN) : (iconClose || getIcon().TREE_NODE_CLOSE))
1242
- })
1243
- ])
1244
- ]
1245
- : [])
1660
+ class: 'vxe-tree--node-line-wrapper'
1661
+ }, [
1662
+ h('div', {
1663
+ class: 'vxe-tree--node-line',
1664
+ style: {
1665
+ height: `${getNodeId(afterTreeList[0]) === nodeid ? 1 : calcTreeLine($xeTree, node, prevNode)}px`
1666
+ }
1667
+ })
1668
+ ])
1246
1669
  : renderEmptyElement($xeTree),
1670
+ h('div', {
1671
+ class: 'vxe-tree--node-item-switcher'
1672
+ }, showIcon && (lazy ? (isLazyLoaded ? hasChild : hasLazyChilds) : hasChild)
1673
+ ? [
1674
+ h('div', {
1675
+ class: 'vxe-tree--node-item-icon',
1676
+ onClick (evnt) {
1677
+ toggleExpandEvent(evnt, node)
1678
+ }
1679
+ }, iconSlot
1680
+ ? getSlotVNs(iconSlot(nParams))
1681
+ : [
1682
+ h('i', {
1683
+ class: isLazyLoading ? (iconLoaded || getIcon().TREE_NODE_LOADED) : (isExpand ? (iconOpen || getIcon().TREE_NODE_OPEN) : (iconClose || getIcon().TREE_NODE_CLOSE))
1684
+ })
1685
+ ])
1686
+ ]
1687
+ : []),
1247
1688
  renderRadio(node, nodeid, isRadioChecked),
1248
1689
  renderCheckbox(node, nodeid, isCheckboxChecked),
1249
1690
  h('div', {
@@ -1251,38 +1692,59 @@ export default defineVxeComponent({
1251
1692
  }, [
1252
1693
  h('div', {
1253
1694
  class: 'vxe-tree--node-item-title'
1254
- }, titleSlot ? getSlotVNs(titleSlot({ node, isExpand })) : `${nodeValue}`),
1695
+ }, titleSlot ? getSlotVNs(titleSlot(nParams)) : `${nodeValue}`),
1255
1696
  extraSlot
1256
1697
  ? h('div', {
1257
1698
  class: 'vxe-tree--node-item-extra'
1258
- }, getSlotVNs(extraSlot({ node, isExpand })))
1699
+ }, getSlotVNs(extraSlot(nParams)))
1259
1700
  : renderEmptyElement($xeTree)
1260
1701
  ])
1261
- ]),
1262
- hasChild && treeExpandedMaps[nodeid]
1263
- ? h('div', {
1264
- class: 'vxe-tree--node-child-wrapper'
1265
- }, childVns)
1266
- : renderEmptyElement($xeTree)
1702
+ ])
1267
1703
  ])
1268
1704
  }
1269
1705
 
1270
- const renderNodeList = () => {
1271
- const { treeList } = reactData
1272
- return h('div', {
1273
- class: 'vxe-tree--node-list-wrapper'
1274
- }, treeList.map(node => renderNode(node)))
1706
+ const renderList = (treeList: any[]) => {
1707
+ const { transform } = props
1708
+ const { treeExpandedMaps } = internalData
1709
+ const childrenField = computeChildrenField.value
1710
+ if (!treeList.length) {
1711
+ return [
1712
+ h('div', {
1713
+ class: 'vxe-tree--empty-placeholder'
1714
+ }, getI18n('vxe.tree.searchEmpty'))
1715
+ ]
1716
+ }
1717
+ const nodeVNs: VNode[] = []
1718
+ treeList.forEach(transform
1719
+ ? (node) => {
1720
+ const nodeid = getNodeId(node)
1721
+ nodeVNs.push(renderNode(node, nodeid))
1722
+ }
1723
+ : (node) => {
1724
+ const nodeid = getNodeId(node)
1725
+ nodeVNs.push(renderNode(node, nodeid))
1726
+ const childList: any[] = XEUtils.get(node, childrenField)
1727
+ const hasChild = childList && childList.length
1728
+ if (hasChild && treeExpandedMaps[nodeid]) {
1729
+ nodeVNs.push(...renderList(childList))
1730
+ }
1731
+ })
1732
+ return nodeVNs
1275
1733
  }
1276
1734
 
1277
1735
  const renderVN = () => {
1278
1736
  const { loading, trigger, showLine } = props
1737
+ const { bodyHeight, topSpaceHeight, treeList } = reactData
1279
1738
  const vSize = computeSize.value
1280
1739
  const radioOpts = computeRadioOpts.value
1281
1740
  const checkboxOpts = computeCheckboxOpts.value
1282
- const treeStyle = computeTreeStyle.value
1283
1741
  const loadingOpts = computeLoadingOpts.value
1284
1742
  const isRowHover = computeIsRowHover.value
1743
+ const treeStyle = computeTreeStyle.value
1285
1744
  const loadingSlot = slots.loading
1745
+ const headerSlot = slots.header
1746
+ const footerSlot = slots.footer
1747
+
1286
1748
  return h('div', {
1287
1749
  ref: refElem,
1288
1750
  class: ['vxe-tree', {
@@ -1293,10 +1755,40 @@ export default defineVxeComponent({
1293
1755
  'node--hover': isRowHover,
1294
1756
  'node--trigger': trigger === 'node',
1295
1757
  'is--loading': loading
1296
- }],
1297
- style: treeStyle
1758
+ }]
1298
1759
  }, [
1299
- renderNodeList(),
1760
+ headerSlot
1761
+ ? h('div', {
1762
+ ref: refHeaderWrapperElem,
1763
+ class: 'vxe-tree--header-wrapper'
1764
+ }, headerSlot({ $tree: $xeTree }))
1765
+ : renderEmptyElement($xeTree),
1766
+ h('div', {
1767
+ ref: refVirtualWrapper,
1768
+ class: 'vxe-tree--node-list-wrapper',
1769
+ style: treeStyle,
1770
+ onScroll: scrollEvent
1771
+ }, [
1772
+ h('div', {
1773
+ class: 'vxe-tree--y-space',
1774
+ style: {
1775
+ height: bodyHeight ? `${bodyHeight}px` : ''
1776
+ }
1777
+ }),
1778
+ h('div', {
1779
+ ref: refVirtualBody,
1780
+ class: 'vxe-tree--node-list-body',
1781
+ style: {
1782
+ transform: `translateY(${topSpaceHeight}px)`
1783
+ }
1784
+ }, renderList(treeList))
1785
+ ]),
1786
+ footerSlot
1787
+ ? h('div', {
1788
+ ref: refFooterWrapperElem,
1789
+ class: 'vxe-tree--footer-wrapper'
1790
+ }, footerSlot({ $tree: $xeTree }))
1791
+ : renderEmptyElement($xeTree),
1300
1792
  /**
1301
1793
  * 加载中
1302
1794
  */
@@ -1321,7 +1813,7 @@ export default defineVxeComponent({
1321
1813
  dataFlag.value++
1322
1814
  })
1323
1815
  watch(dataFlag, () => {
1324
- loadTreeData(props.data || [])
1816
+ loadData(props.data || [])
1325
1817
  })
1326
1818
 
1327
1819
  watch(() => props.checkNodeKey, (val) => {
@@ -1339,14 +1831,59 @@ export default defineVxeComponent({
1339
1831
  updateCheckboxChecked(props.checkNodeKeys || [])
1340
1832
  })
1341
1833
 
1834
+ watch(() => props.filterValue, () => {
1835
+ triggerSearchEvent(new Event('filter'))
1836
+ })
1837
+
1838
+ const hFlag = ref(0)
1839
+ watch(() => props.height, () => {
1840
+ hFlag.value++
1841
+ })
1842
+ watch(() => props.minHeight, () => {
1843
+ hFlag.value++
1844
+ })
1845
+ watch(() => props.maxHeight, () => {
1846
+ hFlag.value++
1847
+ })
1848
+ watch(hFlag, () => {
1849
+ recalculate()
1850
+ })
1851
+
1852
+ onMounted(() => {
1853
+ if (props.autoResize) {
1854
+ const el = refElem.value
1855
+ const parentEl = getParentElem()
1856
+ const resizeObserver = globalResize.create(() => {
1857
+ if (props.autoResize) {
1858
+ recalculate()
1859
+ }
1860
+ })
1861
+ if (el) {
1862
+ resizeObserver.observe(el)
1863
+ }
1864
+ if (parentEl) {
1865
+ resizeObserver.observe(parentEl)
1866
+ }
1867
+ internalData.resizeObserver = resizeObserver
1868
+ }
1869
+
1870
+ globalEvents.on($xeTree, 'resize', handleGlobalResizeEvent)
1871
+ })
1872
+
1342
1873
  onUnmounted(() => {
1343
- reactData.treeList = []
1874
+ const { resizeObserver } = internalData
1875
+ if (resizeObserver) {
1876
+ resizeObserver.disconnect()
1877
+ }
1878
+
1344
1879
  internalData.treeExpandedMaps = {}
1345
1880
  internalData.indeterminateRowMaps = {}
1346
1881
  internalData.nodeMaps = {}
1882
+
1883
+ globalEvents.off($xeTree, 'resize')
1347
1884
  })
1348
1885
 
1349
- loadTreeData(props.data || [])
1886
+ loadData(props.data || [])
1350
1887
 
1351
1888
  $xeTree.renderVN = renderVN
1352
1889