• 技术文章 >web前端 >前端问答

    Ant Design创建一个树形组件,实现编辑、搜索和定位功能

    青灯夜游青灯夜游2022-01-13 18:28:21转载134
    怎么定制Ant Design树形组件实现编辑、搜索和反向定位功能?下面本篇文章给大家介绍一下创建树形组件,实现这些功能的方法,希望对大家有所帮助!

    这次在做了一个树形的展示功能,谁知产品意犹未尽,找我谈话:

    PD: 什么?只有展开收起功能?这怎么行,咱们最基础的要支持编辑,支持搜索,如果可以的话还可以做个反向定位...

    YY: 你咋不早说?需求文档上也没有啊...

    PD: 你看谁家文档一次写到位的?哪家的PD不加需求?

    YY: 话是这样说,可事情不是这么做的...

    PD: 哎呀,别杵着浪费时间了,快去做吧!

    YY: ...

    以上故事纯属虚构,如有雷同请评论区留言...

    树形数据在开发中算是比较常见了,文件夹、组织架构、生物分类、国家地区等等,世间万物的大多数结构都是树形结构。使用树控件可以完整展现其中的层级关系,并具有展开收起选择等交互功能。

    需求分析

    项目仓库:https://github.com/speakice/editable-tree

    1.png

    功能实现

    能实现以上功能的方法库和组件有很多种,这里只讲其中一种,都是Ant Design的组件:

    import { Tree, Dropdown, Menu, Tabs, Input, Switch } from 'antd';import shortid from 'shortid';复制代码

    递归方法

    操作树行数据,最重要的前提是要有一个趁手的递归方法:

    /**
     * 如果需要修改tree,action就返回修改后的item, 不修改就不返回
     */export const deepTree = (tree = [], action = () => {}) => {  return tree.map((item) => {    const newItem = action({ ...item }) || item;    if (newItem.children) {
          newItem.children = deepTree(newItem.children, action);
        }    return newItem;
      });
    };复制代码

    鼠标右键菜单

    右键菜单作用在title上,需要把Dropdown写入树形组件的数据源上:

        <DirectoryTree
              style={{ width: 280 }}
              draggable
              onDrop={onDrop}
              defaultExpandAll
              onRightClick={({ node }) => setRightClickKey(node.key)}
              onSelect={onSelect}
              selectedKeys={rightConnect ? [activeTabKey] : selectedKeys}
              onExpand={onExpand}
              treeData={[
                ...deepTree(treeData, (item) => {              return {
                    ...item,                titleWord: item.title,                title: (                  <Dropdown                    trigger="contextMenu"                    visible={rightClickKey === item.key}                    onVisibleChange={() => setRightClickKey()}
                        overlayStyle={{ width: 80 }}
                        overlay={menu(item)}
                      >                    <div                      style={                        searchWord && item.title.includes(searchWord)
                              ? { color: 'red' }                          : {}
                          }
                        >
                          {item.title}                    </div>                  </Dropdown>
                    ),
                  };
                }),
              ]}
            />复制代码

    关于右键菜单有几点需要补充说明一下:

    .ant-tree-node-content-wrapper {  display: flex;
    }.ant-tree-title {  flex: 1;
    }复制代码
      const menu = (node) => (    <Menu      onClick={({ key, domEvent }) => {
            domEvent.stopPropagation();
            console.log('menuClick', node, key);
            // 如果要添加操作顶层文件夹,可以直接操作
            switch (key) {
              case 'add':
                setTreeData(
                  deepTree(treeData, (item) => {
                    if (item.children && item.key === node.key) {
                      return {
                        ...item,
                        children: [
                          ...item.children,
                          {
                            title: 'new add',
                            key: shortid.generate(),
                            isLeaf: true,
                          },
                        ],
                      };
                    }
                  })
                );
                break;
              case 'delete':
                const outer = treeData.find((item) => item.key === node.key);
                if (outer) {
                  setTreeData(treeData.filter((item) => item.key !== node.key));
                  return;
                }
                setTreeData(
                  deepTree(treeData, (item) => {
                    if (item.children) {
                      return {
                        ...item,
                        children: item.children.filter(
                          ({ key }) => key !== node.key
                        ),
                      };
                    }
                    return item;
                  })
                );
                break;
              case 'edit':
                setTreeData(
                  deepTree(treeData, (item) => {
                    if (item.key === node.key) {
                      console.log('editle', {
                        ...item,
                        title: 'new edit',
                      });
                      return {
                        ...item,
                        title: 'new edit',
                      };
                    }
                    return item;
                  })
                );
                break;
            }
          }}
        >      <Menu.Item key="add">新增</Menu.Item>      <Menu.Item key="delete" danger>
            删除      </Menu.Item>      <Menu.Item key="edit">编辑</Menu.Item>    </Menu>
      );复制代码

    添加/修改/删除功能

    添加功能默认只能给文件夹添加,通过key值判断添加,这里处理的比较简单,只做核心功能演示,代码见上一小节;

    1-2.png

    修改功能也做了简单的实例,在正式项目中一般需要弹窗编辑或者在树组件的title中嵌入输入框,可以使用变量记录正在编辑的item, 最后保存通过递归插入到树形数据中:

    1-3.png

    删除功能做了判断,如果是删除最外层,则直接通过filter过滤,⚠️否则删除功能是通过children来过滤的,这里要特别注意下。

    搜索功能

    搜索功能是通过titile颜色变红来提示的:

    2.png

    实现上也只是做了点击搜索之后搜索,没有实时搜索提示,也没有做搜索词区分,这里可以再截取下字符串来实现,可以见官方实例注意这个默认打开父节点的属性autoExpandParent,否则可能要费些功夫向上递归。

    3.png

    还有一种需求是要过滤数据源,可以对官方实例简单改造后实现;

    Tab反向定位

    4.png

    点击Tree组件item,在右侧添加Tab,或者激活Tab,这可以算是正向定位;那反向定位就是当右侧Tab页切换时左侧Tree组件选中对应item,核心代码也就是指定selectedKeys,相比较而言也不难,难点在默认打开相关父节点,当然前面说过了控制好autoExpandParent这个属性,就好了。

    5.png

    拖拽移动

    拖拽移动一是Tree组件本身支持,二是官方已经给出了拖拽移动实例,我也只是在官方实例稍微做了改造,这里也不多赘述:

    6.png

    结束

    搜索和反向定位的难点其实是在,打开关联文件夹上,不过官方实例中使用了autoExpandParent这个属性,一下子简单了很多。

    时候也不早了,今天就到这里了。

    更多编程相关知识,请访问:编程视频!!

    以上就是Ant Design创建一个树形组件,实现编辑、搜索和定位功能的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    专题推荐:Ant Design 树形组件
    上一篇:整理分享5种纯CSS实现炫酷的文字效果 下一篇:jquery怎样设置数组转字符串

    相关文章推荐

    • AntDesign Vue中表格无法编辑怎么办?(记录下解决方法)• Ant Design作者公布版本更新背后的故事!• 如何安装Ant Design Pro?简单入门指南• Ant Design中如何定制动态主题?聊聊实现方法• Ant Design Vue中如何让Textarea组件有“字数统计”功能• 讲解Homestead、vagrant及VitrualBox虚拟机的概念

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网