@@ -14,6 +14,7 @@ interface ITreeStoreOptions {
1414 defaultExpandAll ?: boolean
1515 load ?: Function
1616 expandOnFilter ?: boolean
17+ maintainCheckOrder ?: boolean
1718}
1819
1920interface IMapData {
@@ -46,6 +47,9 @@ export default class TreeStore extends TreeEventTarget {
4647 /** 当前单选选中节点 key */
4748 private currentSelectedKey : TreeNodeKeyType | null = null
4849
50+ /** 多选选中节点的顺序 */
51+ private checkedNodesOrder : TreeNodeKeyType [ ] = [ ]
52+
4953 //#endregion Properties
5054
5155 constructor ( private readonly options : ITreeStoreOptions ) {
@@ -74,6 +78,8 @@ export default class TreeStore extends TreeEventTarget {
7478 for ( let key in this . mapData ) delete this . mapData [ key ]
7579 // 扁平化之前清空单选选中,如果 value 有值,则是 selectableUnloadKey 有值,会重新设置 currentSelectedKey ;多选选中没有存储在 store 中,因此不必事先清空。
7680 this . currentSelectedKey = null
81+ // 清空选中顺序
82+ this . checkedNodesOrder = [ ]
7783 // 扁平化节点数据
7884 this . flatData = this . flattenData ( this . data )
7985 // 更新未载入多选选中节点
@@ -122,6 +128,20 @@ export default class TreeStore extends TreeEventTarget {
122128 node . checked = value
123129 }
124130
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+
125145 if ( triggerEvent ) {
126146 if ( node . checked ) {
127147 this . emit ( 'check' , node )
@@ -168,6 +188,8 @@ export default class TreeStore extends TreeEventTarget {
168188 triggerEvent : boolean = true ,
169189 triggerDataChange : boolean = true
170190 ) : void {
191+ // 清空选中顺序
192+ this . checkedNodesOrder = [ ]
171193 keys . forEach ( key => {
172194 this . setChecked ( key , value , false , false )
173195 } )
@@ -222,6 +244,8 @@ export default class TreeStore extends TreeEventTarget {
222244 } )
223245 // 清空未加载多选选中节点
224246 this . unloadCheckedKeys = [ ]
247+ // 清空选中顺序
248+ this . checkedNodesOrder = [ ]
225249
226250 this . triggerCheckedChange ( triggerEvent , triggerDataChange )
227251 }
@@ -605,8 +629,10 @@ export default class TreeStore extends TreeEventTarget {
605629 /**
606630 * 获取多选选中节点
607631 * @param ignoreMode 忽略模式,可选择忽略父节点或子节点,默认值是 VTree 的 ignoreMode Prop
632+ * @param maintainCheckOrder 是否保持选中顺序,默认为 false 以保持向后兼容性
608633 */
609- getCheckedNodes ( ignoreMode = this . options . ignoreMode ) : TreeNode [ ] {
634+ getCheckedNodes ( ignoreMode = this . options . ignoreMode , maintainCheckOrder = this . options . maintainCheckOrder ) : TreeNode [ ] {
635+ let checkedNodes : TreeNode [ ]
610636 if ( ignoreMode === ignoreEnum . children ) {
611637 const result : TreeNode [ ] = [ ]
612638 const traversal = ( nodes : TreeNode [ ] ) => {
@@ -619,22 +645,36 @@ export default class TreeStore extends TreeEventTarget {
619645 } )
620646 }
621647 traversal ( this . data )
622- return result
648+ checkedNodes = result
623649 } else {
624- return this . flatData . filter ( node => {
650+ checkedNodes = this . flatData . filter ( node => {
625651 if ( ignoreMode === ignoreEnum . parents )
626652 return node . checked && node . isLeaf
627653 return node . checked
628654 } )
629655 }
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
630669 }
631670
632671 /**
633672 * 获取多选选中的节点 key ,包括未加载的 key
634673 * @param ignoreMode 忽略模式,同 `getCheckedNodes`
674+ * @param maintainCheckOrder 是否保持选中顺序,默认为 false 以保持向后兼容性
635675 */
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 )
638678 . map ( checkedNodes => checkedNodes [ this . options . keyField ] )
639679 . concat ( this . unloadCheckedKeys )
640680 }
@@ -1223,6 +1263,19 @@ export default class TreeStore extends TreeEventTarget {
12231263
12241264 //#region Check nodes
12251265
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+
12261279 /**
12271280 * 向下勾选/取消勾选节点,包括自身
12281281 * @param node 需要向下勾选的节点
@@ -1234,6 +1287,21 @@ export default class TreeStore extends TreeEventTarget {
12341287 value : boolean ,
12351288 filtering : boolean = false
12361289 ) : 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+ }
12371305 node . children . forEach ( child => {
12381306 this . checkNodeDownward ( child , value , filtering )
12391307 } )
@@ -1248,6 +1316,21 @@ export default class TreeStore extends TreeEventTarget {
12481316 return
12491317 node . checked = value
12501318 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+ }
12511334 }
12521335 } else {
12531336 this . checkParentNode ( node )
0 commit comments