瀏覽代碼

fix(tree): fixed `checkedKeys` with `search` mode

修复搜索状态的切换导致的勾选值可能不正确的问题
无木 3 年之前
父節點
當前提交
f707541dda
共有 2 個文件被更改,包括 39 次插入23 次删除
  1. 16 23
      src/components/Tree/src/Tree.vue
  2. 23 0
      src/components/Tree/src/useTree.ts

+ 16 - 23
src/components/Tree/src/Tree.vue

@@ -18,8 +18,8 @@
   import TreeHeader from './TreeHeader.vue';
   import { ScrollContainer } from '/@/components/Container';
 
-  import { omit, get, cloneDeep, concat, uniq } from 'lodash-es';
-  import { isBoolean, isFunction } from '/@/utils/is';
+  import { omit, get, difference } from 'lodash-es';
+  import { isArray, isBoolean, isFunction } from '/@/utils/is';
   import { extendSlots, getSlot } from '/@/utils/helper/tsxHelper';
   import { filter } from '/@/utils/helper/treeHelper';
 
@@ -56,25 +56,6 @@
         searchData: [] as TreeItem[],
       });
 
-      const copyState = {
-        checkedKeys: [],
-      };
-
-      watch(
-        () => searchState.startSearch,
-        (newVal, oldVal) => {
-          if (newVal && !oldVal) {
-            // before search, save current checkedKeys
-            copyState.checkedKeys = cloneDeep(state.checkedKeys);
-          } else if (!newVal && oldVal) {
-            // after search,  restore checkedKeys
-            state.checkedKeys = uniq(concat(state.checkedKeys, copyState.checkedKeys));
-            copyState.checkedKeys = [];
-          }
-        },
-        { immediate: true }
-      );
-
       const treeDataRef = ref<TreeItem[]>([]);
 
       const [createContextMenu] = useContextMenu();
@@ -109,8 +90,19 @@
             emit('update:selectedKeys', v);
           },
           onCheck: (v: CheckKeys, e: CheckEvent) => {
-            state.checkedKeys = v;
-            const rawVal = toRaw(v);
+            let currentValue = toRaw(state.checkedKeys) as Keys;
+            if (isArray(currentValue) && searchState.startSearch) {
+              const { key } = unref(getReplaceFields);
+              currentValue = difference(currentValue, getChildrenKeys(e.node.$attrs.node[key]));
+              if (e.checked) {
+                currentValue.push(e.node.$attrs.node[key]);
+              }
+              state.checkedKeys = currentValue;
+            } else {
+              state.checkedKeys = v;
+            }
+
+            const rawVal = toRaw(state.checkedKeys);
             emit('update:value', rawVal);
             emit('check', rawVal, e);
           },
@@ -134,6 +126,7 @@
         filterByLevel,
         updateNodeByKey,
         getAllKeys,
+        getChildrenKeys,
       } = useTree(treeDataRef, getReplaceFields);
 
       function getIcon(params: Recordable, icon?: string) {

+ 23 - 0
src/components/Tree/src/useTree.ts

@@ -27,6 +27,28 @@ export function useTree(
     return keys as Keys;
   }
 
+  function getChildrenKeys(nodeKey: string | number, list?: TreeDataItem[]): Keys {
+    const keys: Keys = [];
+    const treeData = list || unref(treeDataRef);
+    const { key: keyField, children: childrenField } = unref(getReplaceFields);
+    if (!childrenField || !keyField) return keys;
+    for (let index = 0; index < treeData.length; index++) {
+      const node = treeData[index];
+      const children = node[childrenField];
+      if (nodeKey === node[keyField]) {
+        keys.push(node[keyField]!);
+        if (children && children.length) {
+          keys.push(...(getAllKeys(children) as string[]));
+        }
+      } else {
+        if (children && children.length) {
+          keys.push(...getChildrenKeys(nodeKey, children));
+        }
+      }
+    }
+    return keys as Keys;
+  }
+
   // Update node
   function updateNodeByKey(key: string, node: TreeDataItem, list?: TreeDataItem[]) {
     if (!key) return;
@@ -146,5 +168,6 @@ export function useTree(
     filterByLevel,
     updateNodeByKey,
     getAllKeys,
+    getChildrenKeys,
   };
 }