@@ -14,6 +14,7 @@ interface ITreeStoreOptions {
14
14
defaultExpandAll ?: boolean
15
15
load ?: Function
16
16
expandOnFilter ?: boolean
17
+ maintainCheckOrder ?: boolean
17
18
}
18
19
19
20
interface IMapData {
@@ -46,6 +47,9 @@ export default class TreeStore extends TreeEventTarget {
46
47
/** 当前单选选中节点 key */
47
48
private currentSelectedKey : TreeNodeKeyType | null = null
48
49
50
+ /** 多选选中节点的顺序 */
51
+ private checkedNodesOrder : TreeNodeKeyType [ ] = [ ]
52
+
49
53
//#endregion Properties
50
54
51
55
constructor ( private readonly options : ITreeStoreOptions ) {
@@ -74,6 +78,8 @@ export default class TreeStore extends TreeEventTarget {
74
78
for ( let key in this . mapData ) delete this . mapData [ key ]
75
79
// 扁平化之前清空单选选中,如果 value 有值,则是 selectableUnloadKey 有值,会重新设置 currentSelectedKey ;多选选中没有存储在 store 中,因此不必事先清空。
76
80
this . currentSelectedKey = null
81
+ // 清空选中顺序
82
+ this . checkedNodesOrder = [ ]
77
83
// 扁平化节点数据
78
84
this . flatData = this . flattenData ( this . data )
79
85
// 更新未载入多选选中节点
@@ -122,6 +128,20 @@ export default class TreeStore extends TreeEventTarget {
122
128
node . checked = value
123
129
}
124
130
131
+ // 更新选中顺序
132
+ if ( value ) {
133
+ // 如果节点被选中,将其添加到顺序数组的末尾
134
+ if ( ! this . checkedNodesOrder . includes ( key ) ) {
135
+ this . checkedNodesOrder . push ( key )
136
+ }
137
+ } else {
138
+ // 如果节点被取消选中,从顺序数组中移除
139
+ const index = this . checkedNodesOrder . indexOf ( key )
140
+ if ( index !== - 1 ) {
141
+ this . checkedNodesOrder . splice ( index , 1 )
142
+ }
143
+ }
144
+
125
145
if ( triggerEvent ) {
126
146
if ( node . checked ) {
127
147
this . emit ( 'check' , node )
@@ -168,6 +188,8 @@ export default class TreeStore extends TreeEventTarget {
168
188
triggerEvent : boolean = true ,
169
189
triggerDataChange : boolean = true
170
190
) : void {
191
+ // 清空选中顺序
192
+ this . checkedNodesOrder = [ ]
171
193
keys . forEach ( key => {
172
194
this . setChecked ( key , value , false , false )
173
195
} )
@@ -222,6 +244,8 @@ export default class TreeStore extends TreeEventTarget {
222
244
} )
223
245
// 清空未加载多选选中节点
224
246
this . unloadCheckedKeys = [ ]
247
+ // 清空选中顺序
248
+ this . checkedNodesOrder = [ ]
225
249
226
250
this . triggerCheckedChange ( triggerEvent , triggerDataChange )
227
251
}
@@ -605,8 +629,10 @@ export default class TreeStore extends TreeEventTarget {
605
629
/**
606
630
* 获取多选选中节点
607
631
* @param ignoreMode 忽略模式,可选择忽略父节点或子节点,默认值是 VTree 的 ignoreMode Prop
632
+ * @param maintainCheckOrder 是否保持选中顺序,默认为 false 以保持向后兼容性
608
633
*/
609
- getCheckedNodes ( ignoreMode = this . options . ignoreMode ) : TreeNode [ ] {
634
+ getCheckedNodes ( ignoreMode = this . options . ignoreMode , maintainCheckOrder = this . options . maintainCheckOrder ) : TreeNode [ ] {
635
+ let checkedNodes : TreeNode [ ]
610
636
if ( ignoreMode === ignoreEnum . children ) {
611
637
const result : TreeNode [ ] = [ ]
612
638
const traversal = ( nodes : TreeNode [ ] ) => {
@@ -619,22 +645,36 @@ export default class TreeStore extends TreeEventTarget {
619
645
} )
620
646
}
621
647
traversal ( this . data )
622
- return result
648
+ checkedNodes = result
623
649
} else {
624
- return this . flatData . filter ( node => {
650
+ checkedNodes = this . flatData . filter ( node => {
625
651
if ( ignoreMode === ignoreEnum . parents )
626
652
return node . checked && node . isLeaf
627
653
return node . checked
628
654
} )
629
655
}
656
+
657
+ // 只有在需要保持选中顺序时才进行排序
658
+ if ( maintainCheckOrder ) {
659
+ return checkedNodes . sort ( ( a , b ) => {
660
+ const aIndex = this . checkedNodesOrder . indexOf ( a [ this . options . keyField ] )
661
+ const bIndex = this . checkedNodesOrder . indexOf ( b [ this . options . keyField ] )
662
+ if ( aIndex === - 1 ) return 1
663
+ if ( bIndex === - 1 ) return - 1
664
+ return aIndex - bIndex
665
+ } )
666
+ }
667
+
668
+ return checkedNodes
630
669
}
631
670
632
671
/**
633
672
* 获取多选选中的节点 key ,包括未加载的 key
634
673
* @param ignoreMode 忽略模式,同 `getCheckedNodes`
674
+ * @param maintainCheckOrder 是否保持选中顺序,默认为 false 以保持向后兼容性
635
675
*/
636
- getCheckedKeys ( ignoreMode = this . options . ignoreMode ) : TreeNodeKeyType [ ] {
637
- return this . getCheckedNodes ( ignoreMode )
676
+ getCheckedKeys ( ignoreMode = this . options . ignoreMode , maintainCheckOrder = this . options . maintainCheckOrder ) : TreeNodeKeyType [ ] {
677
+ return this . getCheckedNodes ( ignoreMode , maintainCheckOrder )
638
678
. map ( checkedNodes => checkedNodes [ this . options . keyField ] )
639
679
. concat ( this . unloadCheckedKeys )
640
680
}
@@ -1223,6 +1263,19 @@ export default class TreeStore extends TreeEventTarget {
1223
1263
1224
1264
//#region Check nodes
1225
1265
1266
+ /**
1267
+ * 递归收集节点及其所有子节点的 key,父节点在前,子节点在后
1268
+ */
1269
+ private collectAllKeys ( node : TreeNode ) : TreeNodeKeyType [ ] {
1270
+ const keys : TreeNodeKeyType [ ] = [ node [ this . options . keyField ] ]
1271
+ if ( node . children && node . children . length ) {
1272
+ node . children . forEach ( child => {
1273
+ keys . push ( ...this . collectAllKeys ( child ) )
1274
+ } )
1275
+ }
1276
+ return keys
1277
+ }
1278
+
1226
1279
/**
1227
1280
* 向下勾选/取消勾选节点,包括自身
1228
1281
* @param node 需要向下勾选的节点
@@ -1234,6 +1287,21 @@ export default class TreeStore extends TreeEventTarget {
1234
1287
value : boolean ,
1235
1288
filtering : boolean = false
1236
1289
) : void {
1290
+ // cascade 模式下,父节点整体操作 checkedNodesOrder
1291
+ if ( this . options . cascade && ! node . _parent ) {
1292
+ const keys = this . collectAllKeys ( node )
1293
+ if ( value ) {
1294
+ // 整体插入末尾,去重
1295
+ keys . forEach ( key => {
1296
+ if ( ! this . checkedNodesOrder . includes ( key ) ) {
1297
+ this . checkedNodesOrder . push ( key )
1298
+ }
1299
+ } )
1300
+ } else {
1301
+ // 整体移除
1302
+ this . checkedNodesOrder = this . checkedNodesOrder . filter ( key => ! keys . includes ( key ) )
1303
+ }
1304
+ }
1237
1305
node . children . forEach ( child => {
1238
1306
this . checkNodeDownward ( child , value , filtering )
1239
1307
} )
@@ -1248,6 +1316,21 @@ export default class TreeStore extends TreeEventTarget {
1248
1316
return
1249
1317
node . checked = value
1250
1318
node . indeterminate = false
1319
+
1320
+ // 非 cascade 或子节点单独勾选时,单独插入末尾,去重
1321
+ if ( ! this . options . cascade || node . _parent ) {
1322
+ const key = node [ this . options . keyField ]
1323
+ if ( value ) {
1324
+ if ( ! this . checkedNodesOrder . includes ( key ) ) {
1325
+ this . checkedNodesOrder . push ( key )
1326
+ }
1327
+ } else {
1328
+ const index = this . checkedNodesOrder . indexOf ( key )
1329
+ if ( index !== - 1 ) {
1330
+ this . checkedNodesOrder . splice ( index , 1 )
1331
+ }
1332
+ }
1333
+ }
1251
1334
}
1252
1335
} else {
1253
1336
this . checkParentNode ( node )
0 commit comments