vxe-pc-ui 4.7.4 → 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 (198) 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/table.d.ts +2 -4
  185. package/types/components/tree-select.d.ts +73 -12
  186. package/types/components/tree.d.ts +125 -8
  187. /package/es/icon/{iconfont.1752133996961.ttf → iconfont.1752416456948.ttf} +0 -0
  188. /package/es/icon/{iconfont.1752133996961.woff → iconfont.1752416456948.woff} +0 -0
  189. /package/es/icon/{iconfont.1752133996961.woff2 → iconfont.1752416456948.woff2} +0 -0
  190. /package/es/{iconfont.1752133996961.ttf → iconfont.1752416456948.ttf} +0 -0
  191. /package/es/{iconfont.1752133996961.woff → iconfont.1752416456948.woff} +0 -0
  192. /package/es/{iconfont.1752133996961.woff2 → iconfont.1752416456948.woff2} +0 -0
  193. /package/lib/icon/style/{iconfont.1752133996961.ttf → iconfont.1752416456948.ttf} +0 -0
  194. /package/lib/icon/style/{iconfont.1752133996961.woff → iconfont.1752416456948.woff} +0 -0
  195. /package/lib/icon/style/{iconfont.1752133996961.woff2 → iconfont.1752416456948.woff2} +0 -0
  196. /package/lib/{iconfont.1752133996961.ttf → iconfont.1752416456948.ttf} +0 -0
  197. /package/lib/{iconfont.1752133996961.woff → iconfont.1752416456948.woff} +0 -0
  198. /package/lib/{iconfont.1752133996961.woff2 → iconfont.1752416456948.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,380 @@ 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()
706
820
  }
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)
821
+ return nextTick()
822
+ }
823
+
824
+ const loadYData = (evnt: Event) => {
825
+ const { scrollYStore } = internalData
826
+ const { startIndex, endIndex, visibleSize, offsetSize, rowHeight } = scrollYStore
827
+ const scrollBodyElem = evnt.target as HTMLDivElement
828
+ const scrollTop = scrollBodyElem.scrollTop
829
+ const toVisibleIndex = Math.floor(scrollTop / rowHeight)
830
+ const offsetStartIndex = Math.max(0, toVisibleIndex - 1 - offsetSize)
831
+ const offsetEndIndex = toVisibleIndex + visibleSize + offsetSize
832
+ if (toVisibleIndex <= startIndex || toVisibleIndex >= endIndex - visibleSize - 1) {
833
+ if (startIndex !== offsetStartIndex || endIndex !== offsetEndIndex) {
834
+ scrollYStore.startIndex = offsetStartIndex
835
+ scrollYStore.endIndex = offsetEndIndex
836
+ updateYData()
715
837
  }
716
838
  }
717
839
  }
718
840
 
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
- })
841
+ const scrollEvent = (evnt: Event) => {
842
+ const scrollBodyElem = evnt.target as HTMLDivElement
843
+ const scrollTop = scrollBodyElem.scrollTop
844
+ const scrollLeft = scrollBodyElem.scrollLeft
845
+ const isX = scrollLeft !== internalData.lastScrollLeft
846
+ const isY = scrollTop !== internalData.lastScrollTop
847
+ internalData.lastScrollTop = scrollTop
848
+ internalData.lastScrollLeft = scrollLeft
849
+ if (reactData.scrollYLoad) {
850
+ loadYData(evnt)
730
851
  }
852
+ internalData.lastScrollTime = Date.now()
853
+ dispatchEvent('scroll', { scrollLeft, scrollTop, isX, isY }, evnt)
731
854
  }
732
855
 
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
- }
856
+ const clearScroll = () => {
857
+ const scrollBodyElem = refVirtualWrapper.value
858
+ if (scrollBodyElem) {
859
+ scrollBodyElem.scrollTop = 0
860
+ scrollBodyElem.scrollLeft = 0
748
861
  }
862
+ internalData.lastScrollTop = 0
863
+ internalData.lastScrollLeft = 0
864
+ return nextTick()
749
865
  }
750
866
 
751
867
  const handleNodeClickEvent = (evnt: MouseEvent, node: any) => {
@@ -782,11 +898,11 @@ export default defineVxeComponent({
782
898
  dispatchEvent('node-dblclick', { node }, evnt)
783
899
  }
784
900
 
785
- const handleAsyncTreeExpandChilds = (node: any): Promise<void> => {
901
+ const handleAsyncTreeExpandChilds = (node: any) => {
786
902
  const checkboxOpts = computeCheckboxOpts.value
787
903
  const { loadMethod } = props
788
904
  const { checkStrictly } = checkboxOpts
789
- return new Promise(resolve => {
905
+ return new Promise<void>(resolve => {
790
906
  if (loadMethod) {
791
907
  const { nodeMaps } = internalData
792
908
  const nodeid = getNodeId(node)
@@ -814,12 +930,10 @@ export default defineVxeComponent({
814
930
  if (!checkStrictly && $xeTree.isCheckedByCheckboxNodeId(nodeid)) {
815
931
  handleCheckedCheckboxNode(childRows, true)
816
932
  }
817
- updateNodeLine(node)
818
933
  dispatchEvent('load-success', { node, data: childRecords }, new Event('load-success'))
819
934
  return nextTick()
820
935
  })
821
936
  } else {
822
- updateNodeLine(node)
823
937
  dispatchEvent('load-success', { node, data: childRecords }, new Event('load-success'))
824
938
  }
825
939
  }).catch((e) => {
@@ -828,10 +942,11 @@ export default defineVxeComponent({
828
942
  if (treeExpandLazyLoadedMaps[nodeid]) {
829
943
  treeExpandLazyLoadedMaps[nodeid] = false
830
944
  }
831
- updateNodeLine(node)
832
945
  dispatchEvent('load-error', { node, data: e }, new Event('load-error'))
833
946
  }).finally(() => {
834
- return nextTick()
947
+ handleTreeToList()
948
+ handleData()
949
+ return recalculate()
835
950
  })
836
951
  } else {
837
952
  resolve()
@@ -895,8 +1010,9 @@ export default defineVxeComponent({
895
1010
  })
896
1011
  }
897
1012
  reactData.updateExpandedFlag++
898
- expandNodes.forEach(updateNodeLine)
899
- return Promise.all(result)
1013
+ handleTreeToList()
1014
+ handleData()
1015
+ return Promise.all(result).then(() => recalculate())
900
1016
  }
901
1017
 
902
1018
  const toggleExpandEvent = (evnt: MouseEvent, node: any) => {
@@ -912,8 +1028,7 @@ export default defineVxeComponent({
912
1028
 
913
1029
  const updateCheckboxStatus = () => {
914
1030
  const { transform } = props
915
- const { treeList } = reactData
916
- const { selectCheckboxMaps, indeterminateRowMaps } = internalData
1031
+ const { selectCheckboxMaps, indeterminateRowMaps, afterTreeList } = internalData
917
1032
  const childrenField = computeChildrenField.value
918
1033
  const mapChildrenField = computeMapChildrenField.value
919
1034
  const checkboxOpts = computeCheckboxOpts.value
@@ -921,7 +1036,7 @@ export default defineVxeComponent({
921
1036
  if (!checkStrictly) {
922
1037
  const childRowMaps: Record<string, number> = {}
923
1038
  const childRowList: any[][] = []
924
- XEUtils.eachTree(treeList, (node) => {
1039
+ XEUtils.eachTree(afterTreeList, (node) => {
925
1040
  const nodeid = getNodeId(node)
926
1041
  const childList = node[childrenField]
927
1042
  if (childList && childList.length && !childRowMaps[nodeid]) {
@@ -936,13 +1051,14 @@ export default defineVxeComponent({
936
1051
  const childList: any[] = vals[2]
937
1052
  let sLen = 0 // 已选
938
1053
  let hLen = 0 // 半选
939
- let vLen = 0 // 有效行
1054
+ let vLen = 0 // 有效子行
1055
+ const cLen = childList.length // 子行
940
1056
  childList.forEach(
941
1057
  checkMethod
942
1058
  ? (item) => {
943
1059
  const childNodeid = getNodeId(item)
944
1060
  const isSelect = selectCheckboxMaps[childNodeid]
945
- if (checkMethod({ node: item })) {
1061
+ if (checkMethod({ $tree: $xeTree, node: item })) {
946
1062
  if (isSelect) {
947
1063
  sLen++
948
1064
  } else if (indeterminateRowMaps[childNodeid]) {
@@ -968,8 +1084,27 @@ export default defineVxeComponent({
968
1084
  vLen++
969
1085
  }
970
1086
  )
971
- const isSelected = sLen >= vLen
972
- const halfSelect = !isSelected && (sLen >= 1 || hLen >= 1)
1087
+
1088
+ let isSelected = false
1089
+ if (cLen > 0) {
1090
+ if (vLen > 0) {
1091
+ isSelected = (sLen > 0 || hLen > 0) && sLen >= vLen
1092
+ } else {
1093
+ // 如果存在子项禁用
1094
+ if ((sLen > 0 && sLen >= vLen)) {
1095
+ isSelected = true
1096
+ } else if (selectCheckboxMaps[nodeid]) {
1097
+ isSelected = true
1098
+ } else {
1099
+ isSelected = false
1100
+ }
1101
+ }
1102
+ } else {
1103
+ // 如果无子项
1104
+ isSelected = selectCheckboxMaps[nodeid]
1105
+ }
1106
+ const halfSelect = !isSelected && (sLen > 0 || hLen > 0)
1107
+
973
1108
  if (isSelected) {
974
1109
  selectCheckboxMaps[nodeid] = node
975
1110
  if (indeterminateRowMaps[nodeid]) {
@@ -1003,7 +1138,7 @@ export default defineVxeComponent({
1003
1138
  const { checkStrictly, checkMethod } = checkboxOpts
1004
1139
  let isDisabled = !!checkMethod
1005
1140
  if (checkMethod) {
1006
- isDisabled = !checkMethod({ node })
1141
+ isDisabled = !checkMethod({ $tree: $xeTree, node })
1007
1142
  }
1008
1143
  if (isDisabled) {
1009
1144
  return
@@ -1017,7 +1152,7 @@ export default defineVxeComponent({
1017
1152
  selectCheckboxMaps[nodeid] = node
1018
1153
  }
1019
1154
  if (!checkStrictly) {
1020
- XEUtils.eachTree(XEUtils.get(node, childrenField), (childNode) => {
1155
+ XEUtils.eachTree(XEUtils.get(node, transform ? mapChildrenField : childrenField), (childNode) => {
1021
1156
  const childNodeid = getNodeId(childNode)
1022
1157
  if (isChecked) {
1023
1158
  if (!selectCheckboxMaps[childNodeid]) {
@@ -1072,7 +1207,7 @@ export default defineVxeComponent({
1072
1207
  const { checkMethod } = radioOpts
1073
1208
  let isDisabled = !!checkMethod
1074
1209
  if (checkMethod) {
1075
- isDisabled = !checkMethod({ node })
1210
+ isDisabled = !checkMethod({ $tree: $xeTree, node })
1076
1211
  }
1077
1212
  if (isDisabled) {
1078
1213
  return
@@ -1084,6 +1219,312 @@ export default defineVxeComponent({
1084
1219
  dispatchEvent('radio-change', { node, value, checked: isChecked }, evnt)
1085
1220
  }
1086
1221
 
1222
+ const handleGlobalResizeEvent = () => {
1223
+ const el = refElem.value
1224
+ if (!el || !el.clientWidth) {
1225
+ return
1226
+ }
1227
+ recalculate()
1228
+ }
1229
+
1230
+ const treeMethods: TreeMethods = {
1231
+ dispatchEvent,
1232
+ getNodeId,
1233
+ loadData (data) {
1234
+ return loadData(data || [])
1235
+ },
1236
+ reloadData (data) {
1237
+ return loadData(data || [])
1238
+ },
1239
+ clearCurrentNode () {
1240
+ reactData.currentNode = null
1241
+ return nextTick()
1242
+ },
1243
+ getCurrentNodeId () {
1244
+ const { currentNode } = reactData
1245
+ if (currentNode) {
1246
+ return getNodeId(currentNode)
1247
+ }
1248
+ return null
1249
+ },
1250
+ getCurrentNode () {
1251
+ const { currentNode } = reactData
1252
+ const { nodeMaps } = internalData
1253
+ if (currentNode) {
1254
+ const nodeItem = nodeMaps[getNodeId(currentNode)]
1255
+ if (nodeItem) {
1256
+ return nodeItem.item
1257
+ }
1258
+ }
1259
+ return null
1260
+ },
1261
+ setCurrentNodeId (nodeKey) {
1262
+ const { nodeMaps } = internalData
1263
+ const nodeItem = nodeMaps[nodeKey]
1264
+ reactData.currentNode = nodeItem ? nodeItem.item : null
1265
+ return nextTick()
1266
+ },
1267
+ setCurrentNode (node) {
1268
+ reactData.currentNode = node
1269
+ return nextTick()
1270
+ },
1271
+ clearRadioNode () {
1272
+ reactData.selectRadioKey = null
1273
+ return nextTick()
1274
+ },
1275
+ getRadioNodeId () {
1276
+ return reactData.selectRadioKey || null
1277
+ },
1278
+ getRadioNode () {
1279
+ const { selectRadioKey } = reactData
1280
+ const { nodeMaps } = internalData
1281
+ if (selectRadioKey) {
1282
+ const nodeItem = nodeMaps[selectRadioKey]
1283
+ if (nodeItem) {
1284
+ return nodeItem.item
1285
+ }
1286
+ }
1287
+ return null
1288
+ },
1289
+ setRadioNodeId (nodeKey) {
1290
+ reactData.selectRadioKey = nodeKey
1291
+ return nextTick()
1292
+ },
1293
+ setRadioNode,
1294
+ setCheckboxNode,
1295
+ setCheckboxByNodeId,
1296
+ getCheckboxNodeIds () {
1297
+ const { selectCheckboxMaps } = internalData
1298
+ return Object.keys(selectCheckboxMaps)
1299
+ },
1300
+ getCheckboxNodes () {
1301
+ const { nodeMaps, selectCheckboxMaps } = internalData
1302
+ const list: any[] = []
1303
+ XEUtils.each(selectCheckboxMaps, (item, nodeid) => {
1304
+ const nodeItem = nodeMaps[nodeid]
1305
+ if (nodeItem) {
1306
+ list.push(nodeItem.item)
1307
+ }
1308
+ })
1309
+ return list
1310
+ },
1311
+ clearCheckboxNode () {
1312
+ internalData.selectCheckboxMaps = {}
1313
+ reactData.updateCheckboxFlag++
1314
+ return nextTick().then(() => {
1315
+ return { checkNodeKeys: [] }
1316
+ })
1317
+ },
1318
+ setAllCheckboxNode (checked) {
1319
+ const { transform } = props
1320
+ const selectMaps: Record<string, boolean> = {}
1321
+ const childrenField = computeChildrenField.value
1322
+ const mapChildrenField = computeMapChildrenField.value
1323
+ const checkKeys: string[] = []
1324
+ if (checked) {
1325
+ XEUtils.eachTree(internalData.afterTreeList, (node) => {
1326
+ const nodeid = getNodeId(node)
1327
+ checkKeys.push(nodeid)
1328
+ selectMaps[nodeid] = true
1329
+ }, { children: transform ? mapChildrenField : childrenField })
1330
+ }
1331
+ internalData.selectCheckboxMaps = selectMaps
1332
+ reactData.updateCheckboxFlag++
1333
+ return nextTick().then(() => {
1334
+ return { checkNodeKeys: checkKeys }
1335
+ })
1336
+ },
1337
+ clearExpandNode () {
1338
+ return treeMethods.clearAllExpandNode()
1339
+ },
1340
+ clearAllExpandNode () {
1341
+ const { nodeMaps } = internalData
1342
+ XEUtils.each(nodeMaps, (nodeItem: VxeTreeDefines.NodeCacheItem) => {
1343
+ nodeItem.treeLoaded = false
1344
+ })
1345
+ internalData.treeExpandedMaps = {}
1346
+ reactData.updateExpandedFlag++
1347
+ handleTreeToList()
1348
+ handleData()
1349
+ return recalculate()
1350
+ },
1351
+ setExpandByNodeId (nodeids, expanded) {
1352
+ const { treeExpandedMaps } = internalData
1353
+ if (nodeids) {
1354
+ if (!XEUtils.isArray(nodeids)) {
1355
+ nodeids = [nodeids]
1356
+ }
1357
+ nodeids.forEach((nodeid: string) => {
1358
+ handleSetExpand(nodeid, expanded, treeExpandedMaps)
1359
+ })
1360
+ reactData.updateExpandedFlag++
1361
+ }
1362
+ handleTreeToList()
1363
+ handleData()
1364
+ return recalculate()
1365
+ },
1366
+ getExpandNodeIds () {
1367
+ const { treeExpandedMaps } = internalData
1368
+ return XEUtils.keys(treeExpandedMaps)
1369
+ },
1370
+ getExpandNodes () {
1371
+ const { nodeMaps, treeExpandedMaps } = internalData
1372
+ const list: any[] = []
1373
+ XEUtils.each(treeExpandedMaps, (item, nodeid) => {
1374
+ const nodeItem = nodeMaps[nodeid]
1375
+ if (nodeItem) {
1376
+ list.push(nodeItem.item)
1377
+ }
1378
+ })
1379
+ return list
1380
+ },
1381
+ setExpandNode (nodes, expanded) {
1382
+ const { treeExpandedMaps } = internalData
1383
+ if (nodes) {
1384
+ if (!XEUtils.isArray(nodes)) {
1385
+ nodes = [nodes]
1386
+ }
1387
+ nodes.forEach((node: any) => {
1388
+ const nodeid = getNodeId(node)
1389
+ handleSetExpand(nodeid, expanded, treeExpandedMaps)
1390
+ })
1391
+ reactData.updateExpandedFlag++
1392
+ }
1393
+ handleTreeToList()
1394
+ handleData()
1395
+ return recalculate()
1396
+ },
1397
+ toggleExpandByNodeId (nodeids) {
1398
+ const { treeExpandedMaps } = internalData
1399
+ if (nodeids) {
1400
+ if (!XEUtils.isArray(nodeids)) {
1401
+ nodeids = [nodeids]
1402
+ }
1403
+ nodeids.forEach((nodeid: string) => {
1404
+ handleSetExpand(nodeid, !treeExpandedMaps[nodeid], treeExpandedMaps)
1405
+ })
1406
+ reactData.updateExpandedFlag++
1407
+ }
1408
+ handleTreeToList()
1409
+ handleData()
1410
+ return recalculate()
1411
+ },
1412
+ toggleExpandNode (nodes) {
1413
+ const { treeExpandedMaps } = internalData
1414
+ if (nodes) {
1415
+ if (!XEUtils.isArray(nodes)) {
1416
+ nodes = [nodes]
1417
+ }
1418
+ nodes.forEach((node: any) => {
1419
+ const nodeid = getNodeId(node)
1420
+ handleSetExpand(nodeid, !treeExpandedMaps[nodeid], treeExpandedMaps)
1421
+ })
1422
+ reactData.updateExpandedFlag++
1423
+ }
1424
+ handleTreeToList()
1425
+ handleData()
1426
+ return recalculate()
1427
+ },
1428
+ setAllExpandNode (expanded) {
1429
+ const { transform } = props
1430
+ const { treeExpandedMaps } = internalData
1431
+ const childrenField = computeChildrenField.value
1432
+ const mapChildrenField = computeMapChildrenField.value
1433
+ if (expanded) {
1434
+ XEUtils.eachTree(internalData.afterTreeList, (node) => {
1435
+ const childList: any[] = XEUtils.get(node, childrenField)
1436
+ const hasChild = childList && childList.length
1437
+ if (hasChild) {
1438
+ const nodeid = getNodeId(node)
1439
+ treeExpandedMaps[nodeid] = true
1440
+ }
1441
+ }, { children: transform ? mapChildrenField : childrenField })
1442
+ } else {
1443
+ internalData.treeExpandedMaps = {}
1444
+ }
1445
+ reactData.updateExpandedFlag++
1446
+ handleTreeToList()
1447
+ handleData()
1448
+ return recalculate()
1449
+ },
1450
+ reloadExpandNode (node) {
1451
+ const { lazy } = props
1452
+ if (lazy) {
1453
+ treeMethods.clearExpandLoaded(node)
1454
+ return handleAsyncTreeExpandChilds(node)
1455
+ }
1456
+ return recalculate()
1457
+ },
1458
+ clearExpandLoaded (node) {
1459
+ const { lazy } = props
1460
+ const { nodeMaps } = internalData
1461
+ if (lazy) {
1462
+ const nodeItem = nodeMaps[getNodeId(node)]
1463
+ if (nodeItem) {
1464
+ nodeItem.treeLoaded = false
1465
+ }
1466
+ }
1467
+ return recalculate()
1468
+ },
1469
+ /**
1470
+ * 用于树结构,给行数据加载子节点
1471
+ */
1472
+ loadChildrenNode (node, childRecords) {
1473
+ const { lazy, transform } = props
1474
+ const { nodeMaps } = internalData
1475
+ if (!lazy) {
1476
+ return Promise.resolve([])
1477
+ }
1478
+ const childrenField = computeChildrenField.value
1479
+ const mapChildrenField = computeMapChildrenField.value
1480
+ const parentNodeItem = nodeMaps[getNodeId(node)]
1481
+ const parentLevel = parentNodeItem ? parentNodeItem.level : 0
1482
+ const parentNodes = parentNodeItem ? parentNodeItem.nodes : []
1483
+ return createNode(childRecords).then((nodeList) => {
1484
+ XEUtils.eachTree(nodeList, (childRow, index, items, path, parent, nodes) => {
1485
+ const itemNodeId = getNodeId(childRow)
1486
+ nodeMaps[itemNodeId] = {
1487
+ item: node,
1488
+ index: -1,
1489
+ items,
1490
+ parent: parent || parentNodeItem.item,
1491
+ nodes: parentNodes.concat(nodes),
1492
+ level: parentLevel + nodes.length,
1493
+ treeIndex: -1,
1494
+ lineCount: 0,
1495
+ treeLoaded: false
1496
+ }
1497
+ }, { children: childrenField })
1498
+ node[childrenField] = nodeList
1499
+ if (transform) {
1500
+ node[mapChildrenField] = nodeList
1501
+ }
1502
+ updateAfterDataIndex()
1503
+ return nodeList
1504
+ })
1505
+ },
1506
+ isExpandByNode,
1507
+ isCheckedByRadioNodeId,
1508
+ isCheckedByRadioNode,
1509
+ isCheckedByCheckboxNodeId,
1510
+ isIndeterminateByCheckboxNode,
1511
+ isCheckedByCheckboxNode,
1512
+ getCheckboxIndeterminateNodes () {
1513
+ const { nodeMaps, indeterminateRowMaps } = internalData
1514
+ const list: any[] = []
1515
+ XEUtils.each(indeterminateRowMaps, (item, nodeid) => {
1516
+ const nodeItem = nodeMaps[nodeid]
1517
+ if (nodeItem) {
1518
+ list.push(nodeItem.item)
1519
+ }
1520
+ })
1521
+ return list
1522
+ },
1523
+ recalculate,
1524
+ scrollTo,
1525
+ clearScroll
1526
+ }
1527
+
1087
1528
  const treePrivateMethods: TreePrivateMethods = {
1088
1529
  }
1089
1530
 
@@ -1093,11 +1534,11 @@ export default defineVxeComponent({
1093
1534
  const { showRadio } = props
1094
1535
  const radioOpts = computeRadioOpts.value
1095
1536
  const { showIcon, checkMethod, visibleMethod } = radioOpts
1096
- const isVisible = !visibleMethod || visibleMethod({ node })
1537
+ const isVisible = !visibleMethod || visibleMethod({ $tree: $xeTree, node })
1097
1538
  let isDisabled = !!checkMethod
1098
1539
  if (showRadio && showIcon && isVisible) {
1099
1540
  if (checkMethod) {
1100
- isDisabled = !checkMethod({ node })
1541
+ isDisabled = !checkMethod({ $tree: $xeTree, node })
1101
1542
  }
1102
1543
  return h('div', {
1103
1544
  class: ['vxe-tree--radio-option', {
@@ -1123,11 +1564,11 @@ export default defineVxeComponent({
1123
1564
  const checkboxOpts = computeCheckboxOpts.value
1124
1565
  const { showIcon, checkMethod, visibleMethod } = checkboxOpts
1125
1566
  const isIndeterminate = isIndeterminateByCheckboxNodeid(nodeid)
1126
- const isVisible = !visibleMethod || visibleMethod({ node })
1567
+ const isVisible = !visibleMethod || visibleMethod({ $tree: $xeTree, node })
1127
1568
  let isDisabled = !!checkMethod
1128
1569
  if (showCheckbox && showIcon && isVisible) {
1129
1570
  if (checkMethod) {
1130
- isDisabled = !checkMethod({ node })
1571
+ isDisabled = !checkMethod({ $tree: $xeTree, node })
1131
1572
  }
1132
1573
  return h('div', {
1133
1574
  class: ['vxe-tree--checkbox-option', {
@@ -1149,10 +1590,10 @@ export default defineVxeComponent({
1149
1590
  return renderEmptyElement($xeTree)
1150
1591
  }
1151
1592
 
1152
- const renderNode = (node: any): VNode => {
1593
+ const renderNode = (node: any, nodeid: string) => {
1153
1594
  const { lazy, showRadio, showCheckbox, showLine, indent, iconOpen, iconClose, iconLoaded, showIcon } = props
1154
1595
  const { currentNode, selectRadioKey, updateExpandedFlag } = reactData
1155
- const { nodeMaps, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData
1596
+ const { afterTreeList, nodeMaps, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData
1156
1597
  const childrenField = computeChildrenField.value
1157
1598
  const titleField = computeTitleField.value
1158
1599
  const hasChildField = computeHasChildField.value
@@ -1161,33 +1602,14 @@ export default defineVxeComponent({
1161
1602
  const iconSlot = slots.icon
1162
1603
  const titleSlot = slots.title
1163
1604
  const extraSlot = slots.extra
1164
- const nodeid = getNodeId(node)
1165
1605
  const isExpand = updateExpandedFlag && treeExpandedMaps[nodeid]
1166
1606
  const nodeItem = nodeMaps[nodeid]
1167
1607
  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
- }
1608
+ const nLevel = nodeItem.level
1186
1609
 
1187
1610
  let isRadioChecked = false
1188
1611
  if (showRadio) {
1189
- // eslint-disable-next-line eqeqeq
1190
- isRadioChecked = nodeid == selectRadioKey
1612
+ isRadioChecked = nodeid === String(selectRadioKey)
1191
1613
  }
1192
1614
 
1193
1615
  let isCheckboxChecked = false
@@ -1203,9 +1625,12 @@ export default defineVxeComponent({
1203
1625
  hasLazyChilds = node[hasChildField]
1204
1626
  isLazyLoaded = !!nodeItem.treeLoaded
1205
1627
  }
1628
+ const prevNode = nodeItem.items[nodeItem.treeIndex - 1]
1629
+ const nParams = { node, isExpand }
1206
1630
 
1207
1631
  return h('div', {
1208
- class: ['vxe-tree--node-wrapper', `node--level-${nodeItem.level}`],
1632
+ key: nodeid,
1633
+ class: ['vxe-tree--node-wrapper', `node--level-${nLevel}`],
1209
1634
  nodeid
1210
1635
  }, [
1211
1636
  h('div', {
@@ -1215,7 +1640,7 @@ export default defineVxeComponent({
1215
1640
  'is-checkbox--checked': isCheckboxChecked
1216
1641
  }],
1217
1642
  style: {
1218
- paddingLeft: `${(nodeItem.level - 1) * (indent || 1)}px`
1643
+ paddingLeft: `${(nLevel - 1) * (indent || 1)}px`
1219
1644
  },
1220
1645
  onClick (evnt) {
1221
1646
  handleNodeClickEvent(evnt, node)
@@ -1224,26 +1649,36 @@ export default defineVxeComponent({
1224
1649
  handleNodeDblclickEvent(evnt, node)
1225
1650
  }
1226
1651
  }, [
1227
- showIcon || showLine
1652
+ showLine
1228
1653
  ? 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
- : [])
1654
+ class: 'vxe-tree--node-line-wrapper'
1655
+ }, [
1656
+ h('div', {
1657
+ class: 'vxe-tree--node-line',
1658
+ style: {
1659
+ height: `${getNodeId(afterTreeList[0]) === nodeid ? 1 : calcTreeLine($xeTree, node, prevNode)}px`
1660
+ }
1661
+ })
1662
+ ])
1246
1663
  : renderEmptyElement($xeTree),
1664
+ h('div', {
1665
+ class: 'vxe-tree--node-item-switcher'
1666
+ }, showIcon && (lazy ? (isLazyLoaded ? hasChild : hasLazyChilds) : hasChild)
1667
+ ? [
1668
+ h('div', {
1669
+ class: 'vxe-tree--node-item-icon',
1670
+ onClick (evnt) {
1671
+ toggleExpandEvent(evnt, node)
1672
+ }
1673
+ }, iconSlot
1674
+ ? getSlotVNs(iconSlot(nParams))
1675
+ : [
1676
+ h('i', {
1677
+ class: isLazyLoading ? (iconLoaded || getIcon().TREE_NODE_LOADED) : (isExpand ? (iconOpen || getIcon().TREE_NODE_OPEN) : (iconClose || getIcon().TREE_NODE_CLOSE))
1678
+ })
1679
+ ])
1680
+ ]
1681
+ : []),
1247
1682
  renderRadio(node, nodeid, isRadioChecked),
1248
1683
  renderCheckbox(node, nodeid, isCheckboxChecked),
1249
1684
  h('div', {
@@ -1251,38 +1686,59 @@ export default defineVxeComponent({
1251
1686
  }, [
1252
1687
  h('div', {
1253
1688
  class: 'vxe-tree--node-item-title'
1254
- }, titleSlot ? getSlotVNs(titleSlot({ node, isExpand })) : `${nodeValue}`),
1689
+ }, titleSlot ? getSlotVNs(titleSlot(nParams)) : `${nodeValue}`),
1255
1690
  extraSlot
1256
1691
  ? h('div', {
1257
1692
  class: 'vxe-tree--node-item-extra'
1258
- }, getSlotVNs(extraSlot({ node, isExpand })))
1693
+ }, getSlotVNs(extraSlot(nParams)))
1259
1694
  : renderEmptyElement($xeTree)
1260
1695
  ])
1261
- ]),
1262
- hasChild && treeExpandedMaps[nodeid]
1263
- ? h('div', {
1264
- class: 'vxe-tree--node-child-wrapper'
1265
- }, childVns)
1266
- : renderEmptyElement($xeTree)
1696
+ ])
1267
1697
  ])
1268
1698
  }
1269
1699
 
1270
- const renderNodeList = () => {
1271
- const { treeList } = reactData
1272
- return h('div', {
1273
- class: 'vxe-tree--node-list-wrapper'
1274
- }, treeList.map(node => renderNode(node)))
1700
+ const renderList = (treeList: any[]) => {
1701
+ const { transform } = props
1702
+ const { treeExpandedMaps } = internalData
1703
+ const childrenField = computeChildrenField.value
1704
+ if (!treeList.length) {
1705
+ return [
1706
+ h('div', {
1707
+ class: 'vxe-tree--empty-placeholder'
1708
+ }, getI18n('vxe.tree.searchEmpty'))
1709
+ ]
1710
+ }
1711
+ const nodeVNs: VNode[] = []
1712
+ treeList.forEach(transform
1713
+ ? (node) => {
1714
+ const nodeid = getNodeId(node)
1715
+ nodeVNs.push(renderNode(node, nodeid))
1716
+ }
1717
+ : (node) => {
1718
+ const nodeid = getNodeId(node)
1719
+ nodeVNs.push(renderNode(node, nodeid))
1720
+ const childList: any[] = XEUtils.get(node, childrenField)
1721
+ const hasChild = childList && childList.length
1722
+ if (hasChild && treeExpandedMaps[nodeid]) {
1723
+ nodeVNs.push(...renderList(childList))
1724
+ }
1725
+ })
1726
+ return nodeVNs
1275
1727
  }
1276
1728
 
1277
1729
  const renderVN = () => {
1278
1730
  const { loading, trigger, showLine } = props
1731
+ const { bodyHeight, topSpaceHeight, treeList } = reactData
1279
1732
  const vSize = computeSize.value
1280
1733
  const radioOpts = computeRadioOpts.value
1281
1734
  const checkboxOpts = computeCheckboxOpts.value
1282
- const treeStyle = computeTreeStyle.value
1283
1735
  const loadingOpts = computeLoadingOpts.value
1284
1736
  const isRowHover = computeIsRowHover.value
1737
+ const treeStyle = computeTreeStyle.value
1285
1738
  const loadingSlot = slots.loading
1739
+ const headerSlot = slots.header
1740
+ const footerSlot = slots.footer
1741
+
1286
1742
  return h('div', {
1287
1743
  ref: refElem,
1288
1744
  class: ['vxe-tree', {
@@ -1293,10 +1749,40 @@ export default defineVxeComponent({
1293
1749
  'node--hover': isRowHover,
1294
1750
  'node--trigger': trigger === 'node',
1295
1751
  'is--loading': loading
1296
- }],
1297
- style: treeStyle
1752
+ }]
1298
1753
  }, [
1299
- renderNodeList(),
1754
+ headerSlot
1755
+ ? h('div', {
1756
+ ref: refHeaderWrapperElem,
1757
+ class: 'vxe-tree--header-wrapper'
1758
+ }, headerSlot({ $tree: $xeTree }))
1759
+ : renderEmptyElement($xeTree),
1760
+ h('div', {
1761
+ ref: refVirtualWrapper,
1762
+ class: 'vxe-tree--node-list-wrapper',
1763
+ style: treeStyle,
1764
+ onScroll: scrollEvent
1765
+ }, [
1766
+ h('div', {
1767
+ class: 'vxe-select--y-space',
1768
+ style: {
1769
+ height: bodyHeight ? `${bodyHeight}px` : ''
1770
+ }
1771
+ }),
1772
+ h('div', {
1773
+ ref: refVirtualBody,
1774
+ class: 'vxe-tree--node-list-body',
1775
+ style: {
1776
+ transform: `translateY(${topSpaceHeight}px)`
1777
+ }
1778
+ }, renderList(treeList))
1779
+ ]),
1780
+ footerSlot
1781
+ ? h('div', {
1782
+ ref: refFooterWrapperElem,
1783
+ class: 'vxe-tree--footer-wrapper'
1784
+ }, footerSlot({ $tree: $xeTree }))
1785
+ : renderEmptyElement($xeTree),
1300
1786
  /**
1301
1787
  * 加载中
1302
1788
  */
@@ -1321,7 +1807,7 @@ export default defineVxeComponent({
1321
1807
  dataFlag.value++
1322
1808
  })
1323
1809
  watch(dataFlag, () => {
1324
- loadTreeData(props.data || [])
1810
+ loadData(props.data || [])
1325
1811
  })
1326
1812
 
1327
1813
  watch(() => props.checkNodeKey, (val) => {
@@ -1339,14 +1825,59 @@ export default defineVxeComponent({
1339
1825
  updateCheckboxChecked(props.checkNodeKeys || [])
1340
1826
  })
1341
1827
 
1828
+ watch(() => props.filterValue, () => {
1829
+ triggerSearchEvent(new Event('filter'))
1830
+ })
1831
+
1832
+ const hFlag = ref(0)
1833
+ watch(() => props.height, () => {
1834
+ hFlag.value++
1835
+ })
1836
+ watch(() => props.minHeight, () => {
1837
+ hFlag.value++
1838
+ })
1839
+ watch(() => props.maxHeight, () => {
1840
+ hFlag.value++
1841
+ })
1842
+ watch(hFlag, () => {
1843
+ recalculate()
1844
+ })
1845
+
1846
+ onMounted(() => {
1847
+ if (props.autoResize) {
1848
+ const el = refElem.value
1849
+ const parentEl = getParentElem()
1850
+ const resizeObserver = globalResize.create(() => {
1851
+ if (props.autoResize) {
1852
+ recalculate()
1853
+ }
1854
+ })
1855
+ if (el) {
1856
+ resizeObserver.observe(el)
1857
+ }
1858
+ if (parentEl) {
1859
+ resizeObserver.observe(parentEl)
1860
+ }
1861
+ internalData.resizeObserver = resizeObserver
1862
+ }
1863
+
1864
+ globalEvents.on($xeTree, 'resize', handleGlobalResizeEvent)
1865
+ })
1866
+
1342
1867
  onUnmounted(() => {
1343
- reactData.treeList = []
1868
+ const { resizeObserver } = internalData
1869
+ if (resizeObserver) {
1870
+ resizeObserver.disconnect()
1871
+ }
1872
+
1344
1873
  internalData.treeExpandedMaps = {}
1345
1874
  internalData.indeterminateRowMaps = {}
1346
1875
  internalData.nodeMaps = {}
1876
+
1877
+ globalEvents.off($xeTree, 'resize')
1347
1878
  })
1348
1879
 
1349
- loadTreeData(props.data || [])
1880
+ loadData(props.data || [])
1350
1881
 
1351
1882
  $xeTree.renderVN = renderVN
1352
1883