记录:react+antd 树型控件初始化默认选中

541 阅读2分钟

antd 树型控件默认选中数据来自于接口(接口采用的是ahooks),当初始化时接口没有请求到数据,此时是undefined,树型控件初始化就无法默认选中(数据是前端写死的,使用里面的默认展开,默认选中事件,直接调用文档的API即可,如果数据是从后端获取的,那么就需要作一些改动) antd跟默认相关的前缀有default的都只是第一次有用,第二次就没用了。

方法一

import {Button, Form, notification, Space, Tree} from 'antd';
import {PageContainer} from '@ant-design/pro-layout';
import {history} from '@@/core/history';
import {get_menu_data_roleId, get_role_menu, post_add_menu} from '@/services/SystemSettings';
import {useRequest} from 'ahooks';
import {useEffect, useImperativeHandle, useMemo, useRef, useState} from "react";

const Index = () => {
  /**子组件的实例属性输出到父组件**/
  const ref1 = useRef<any>(null);

  /**tree树形源数据**/
  const [SalesData, setSalesData] = useState<any[]>([]);
  
  /**菜单回显接口**/
  const FetchData = useRequest(
    () => {
      return get_menu_data_roleId({
        roleId: history.location?.query?.roleId,
      });
    },
    {},
  );

  /**销售管理定义树形结构可展开**/
  const [expandedKeys, setExpandedKeys] = useState(['1550382838808662018']);
  /**销售管理树形定义**/
  const SalesTree = (props: any) => {
    const {treeData, chooseKey, getDataRef} = props;
    const [_choosekeys, _setChooseKeys] = useState<React.Key[]>([]);
    /**可展开处理**/
    const onExpand = (expandedKeysValue: any) => {
      console.log('onExpand', expandedKeysValue);
      const deepCopyKeys = Object.assign([], expandedKeysValue);
      setExpandedKeys(deepCopyKeys);
    };
    /**计算缓存**/
    const _childKeys = useMemo(() => {
      const handleKeys = (trees: any): string[] => {
        let arr: string[] = [];
        for (let i = 0; i < trees.length; i++) {
          const _child = trees[i].children;
          if (!_child || _child?.length === 0) {
            arr.push(trees[i].key + '');
          } else {
            if (!!_child) {
              const keys = handleKeys(_child);
              arr = [...arr, ...keys];
            }
          }
        }
        return arr;
      };
      if (!chooseKey || !treeData) {
        return [];
      }
      return handleKeys(treeData);
    }, [treeData, chooseKey]);
    //子组件返回给父组件自身的状态和方法ref
    useImperativeHandle(getDataRef, () => {
      return {
        getChooseKey: () => {
          const getChoosekeysParents = (_keys: React.Key[]) => {
            let _arr: any[] = [];
            const loopArr = (trees: any[], parentsKeys: any[] = []) => {
              console.log(parentsKeys, 'parentsKeys');
              for (let i = 0; i < trees.length; i++) {
                const _child = trees[i].children;
                const _item = trees[i].key;
                console.log(_item, '_item');
                if (_child && _child.length > 0) {
                  loopArr(_child, [...parentsKeys, _item]);
                } else {
                  if (_keys.includes(_item)) {
                    _arr = [..._arr, ...parentsKeys];
                  }
                }
              }
            };
            if (treeData) {
              loopArr(treeData);
            }
            return Array.from(new Set(_arr));
          };
          const childrenKeys = _childKeys.filter((_item) => _choosekeys.includes(_item));
          const parentsKeys = getChoosekeysParents(childrenKeys);
          return Array.from(new Set([...childrenKeys, ...parentsKeys])) as any;
        },
      };
    });
    useEffect(() => {
      if (chooseKey && treeData) {
        _setChooseKeys(() => {
          return _childKeys.filter((_item) => chooseKey.includes(_item));
        });
      }
    }, [chooseKey, treeData, _childKeys]);
    return (
      <>
        <Tree
          checkable
          expandedKeys={expandedKeys}
          onExpand={onExpand}
          treeData={treeData}
          checkedKeys={_choosekeys}
          onCheck={(checkedKeysValue) => {
            if (checkedKeysValue instanceof Array) {
              _setChooseKeys(checkedKeysValue);
            }
          }}
        />
      </>
    );
  };
    return (
      <>
        <Tree
          checkable
          expandedKeys={InventoryexpandedKeys}
          onExpand={onExpand}
          treeData={treeData}
          checkedKeys={_choosekeys}
          onCheck={(checkedKeysValue) => {
            if (checkedKeysValue instanceof Array) {
              _setChooseKeys(checkedKeysValue);
            }
          }}
        />
      </>
    );
  };
  /*接口*菜单树源数据**/
  useRequest(
    () => {
      return get_role_menu({});
    },
    {
      onSuccess: (res: any) => {
        [res.data?.at(0)].forEach((item: any) => {
          item.key = item.id;
          item.title = item.name;
          item.children.forEach((_item: any) => {
            _item.key = _item.id;
            _item.title = _item.name;
          })
        });
        setSalesData([res.data?.at(0)]);
      },
    },
  );
  /*接口*新增_编辑菜单**/
  const AddMenu = useRequest(
    () => {
      const _value: any = [];
      const idList1 = ref1.current?.getChooseKey() || [];
      _value.push(idList1)

      /**处理选择数据数组合并**/
      const menuListId = _value.flat()
        .filter((item: any) => {
          return item != undefined;
        });
      return post_add_menu({
        menuIdList: menuListId || [],
        roleId: history.location?.query?.roleId,
      });

    },
    {
      manual: true,
      onSuccess: () => {
        notification.success({
          message: '新增/编辑菜单权限成功',
        });
        history.push('/SystemSettings/RolePermissions');
      },
      onError: () => {
        notification.error({
          message: '新增/编辑菜单权限失败',
        });
      },
    },
  );

  return (
    <>
      <PageContainer>
              <Button
                htmlType={'submit'}
                type="primary"
                onClick={() => {
                  AddMenu.run();
                }}
              >
                保存
              </Button>
        
            <div className={style.border}/>
            <div style={{margin: 10}}>
              <div className={style.table}>
                <div className={style.tree_one}>
                //引用定义tree组件
           <SalesTree treeData={SalesData} chooseKey={FetchData.data?.data} getDataRef={ref1}/>
                </div>
        </div>
      </PageContainer>
    </>
  );
};
export default Index;

方法二

import style from './Welcome.less'
import {SettingFilled} from "@ant-design/icons";
import {Modal, notification, Space, Tag, Tree} from "antd";
import React, {useEffect, useState} from "react";
import {useRequest} from "ahooks";
import {get_menu_data, get_user_data, get_user_menu, post_addmenu} from "@/services/SystemSettings";
import {history} from "@@/core/history";

const Index = () => {
  const [visible, setVisible] = useState(false);
  /**tree树型常用菜单树定义**/
  const [Institutions, setInstitutions] = useState<any>();
  const [expandedKeys, setExpandedKeys] = useState(['1550382838808662017']);
  const [checkedKeys, setCheckedKeys] = useState<React.Key[]>();
  const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
  const [AddMenu, setAddMenu] = useState<any>();
  const [loading, setLoading] = useState<boolean>(true);
  const [Trigger, setTrigger] = useState<any>()
  /**回显**/
  const FetchData = useRequest(() => {
    return get_menu_data({});
  }, {
    onSuccess(res: any) {
      setTrigger(res.data);
    }
  });
  useEffect(() => {
    if (Trigger instanceof Array) {
      setLoading(false);
      setCheckedKeys(Trigger)
    }
  }, [Trigger])
  /**树形菜单接口**/
  useRequest(get_user_data, {
    onSuccess: (res) => {
      res.data.forEach((item: any) => {
        item.title = item.name;
        item.key = item.id;
        item.children.forEach((_item: any) => {
          _item.key = _item.id;
          _item.title = _item.name;
        })
      });
      const tree = [
        {
          title: '菜单',
          key: '1550382838808662017',
          children: res.data,
        },
      ];
      setInstitutions(tree);
    },
  });
  /**设置常用菜单**/
  const addTree = useRequest(() => {
    if (AddMenu) {
      const isAdd = AddMenu.length >= 14 ? notification.success({message: '常用菜单选择请小于10个!!!'}) : AddMenu || []
      return post_addmenu(isAdd || []);
    } else {
      return post_addmenu([]);
    }
  }, {
    manual: true,
    onSuccess: () => {
      notification.success({
        message: '设置菜单成功!'
      });
      history.push('/');
    },
    onError: () => {
      notification.error({
        message: '设置菜单失败,请检查!'
      })
    }
  });
  /**树形**/
  const TreeMenu = () => {
    //++++**可展开处理**++++++
    const onExpand = (expandedKeysValue: any) => {
      console.log('onExpand', expandedKeysValue);
      const deepCopyKeys = Object.assign([], expandedKeysValue);
      setExpandedKeys(deepCopyKeys);
    };
    const onCheck = (checkedKeysValue: any, checkedNodes: any) => {
      setAddMenu(checkedKeysValue.concat(checkedNodes.halfCheckedKeys));
      setCheckedKeys(checkedKeysValue);
    };
    const onSelect = (selectedKeysValue: React.Key[], info: any) => {
      console.log('onSelect', info);
      setSelectedKeys(selectedKeysValue);
    };
    return <div>
      {loading ? null : <Tree
        height={300}
        checkable
        onExpand={onExpand}
        expandedKeys={expandedKeys}
        onCheck={onCheck}
        checkedKeys={checkedKeys}
        onSelect={onSelect}
        selectedKeys={selectedKeys}
        treeData={Institutions}
      />}
    </div>
  };
  return <>
    <div className={'container'}>
      <div className={style.style_top}>常用功能</div>
      <div>
        <SettingFilled style={{fontSize: 24}} onClick={() => {
          setVisible(true);
          FetchData.run();
        }}/>
        <Modal
          title="常用菜单设置"
          centered
          visible={visible}
          onOk={() => {
            setVisible(false);
            addTree.run();
          }}
          onCancel={() => setVisible(false)}
        >
          <TreeMenu/>
        </Modal>
      </div>
    </div>
  </>
}
export default Index;