概述

在网站业务开发中,经常遇到的一个需求就是,级联选择。

实现

先给出实现后的效果:

后端

后端业务Service类实现如下:

public List<CmdbVo> listDepartment() {String url = cmdbUrl + String.format(DEPARTMENTS, cmdbKey);try {Resp resp = JSONObject.parseObject(HttpUtil.doGet(url), Resp.class);if (resp != null && resp.getCode() == 0) {List<CmdbVo> cmdbVoList = Lists.newArrayListWithCapacity(resp.getContent().size());resp.getContent().forEach(x -> {CmdbVo vo = new CmdbVo();BeanUtils.copyProperties(x, vo);cmdbVoList.add(vo);});return cmdbVoList;}} catch (Exception e) {log.error("listDepartment failed: ", e);}return Collections.emptyList();
}

HttpUtil.doGet(url)实现的主要逻辑很简单,就是调用一下外部接口,http://100.111.55.67:9999/cmdb/v0.2.0/departments?page_size=1000,接口返回数据格式如下:

{"code": 0,"content": [{"id": "4561","level": 1,"name": "业务后台","parent_id": "1","parent_name": "信仰科技"}],"msg": "success"
}

CmdbModel实例类POJO用于接收返回的数据。

@Data
public class CmdbModel {private Integer id;private String name;@JSONField(name = "parent_id")private Integer parentId;
}

CmdbVo是暴露给前端的视图类。和上面的实体类字段一模一样,至于个中原因,可查看文档:FastJson序列化和反序列化问题记录

@Data
public class CmdbVo {private Integer id;private String name;private Integer parentId;// 级联效果关键点List<CmdbVo> children;
}

现在要实现级联效果,仅仅依赖上面的方法是不够的。

此处打断一下,让我们从前端角度来思考。鉴于我们使用的组件是ant design,官方给出的文档:Cascader级联选择。官方实例很简单,需要value,label,children 3个字段数据,label就是页面看到的问题,value是label标签对于的文本数据,children是子集。

基于此,我们的改造如下:

  1. CmdbVo增加一个字段List<CmdbVo> children;
  2. 返回return cmdbVoList;变成:return this.getFatherNode(cmdbVoList);

需要的工具类方法

/*** 获取父节点*/
public List<CmdbVo> getFatherNode(List<CmdbVo> cmdbVoList) {List<CmdbVo> newTreeDataList = new ArrayList<>();for (CmdbVo item : cmdbVoList) {if (item.getParentId() == null || item.getParentId() <= 1) {// 获取父节点下的子节点item.setChildren(getChildrenNode(item.getId(), cmdbVoList));List<CmdbVo> children = item.getChildren();if (CollectionUtils.isEmpty(children)) {item.setChildren(Collections.emptyList());}newTreeDataList.add(item);}}return newTreeDataList;
}/*** 获取子节点*/
private static List<CmdbVo> getChildrenNode(Integer pid, List<CmdbVo> treeDataList) {List<CmdbVo> newTreeDataList = new ArrayList<>();for (CmdbVo item : treeDataList) {if (item.getParentId() == null) {continue;}// 这是一个子节点if (item.getParentId().equals(pid)) {// 递归获取子节点下的子节点item.setChildren( getChildrenNode(item.getId(), treeDataList));List<CmdbVo> children = item.getChildren();if (CollectionUtils.isEmpty(children)) {item.setChildren(Collections.emptyList());}newTreeDataList.add(item);}}return newTreeDataList;
}

数据表

另外值得一提的是,数据表域对象PO实体类属性定义为String,直接把层级以数组的形式存储下来:

故而有一个前端JSON解析过程。

前端

import {getDepartmentIdList,} from '@/pages/Board/service'
import ViCascader from "@/components/Customize/Vi_Cascader";const [departmentIds, setDepartmentIds] = useState<any>([])useEffect(() => {// 部门域getDepartmentIdList().then((res: any) => {setDepartmentIds(res.data)})}, [])// 搜索const filter: any = (inputValue: string, path: any) => {return path.some((option: any) => option.name?.toLowerCase().indexOf(inputValue.toLowerCase()) > -1,);};useEffect(() => {if (modalData.type !== 'add') {let param: any = {};param = {...modalData.data,// 编辑时需要解析一下数据departmentId: modalData?.data?.departmentId ? JSON.parse(modalData?.data?.departmentId) : [],};}}, []);return (<div style={{height: 'calc(100vh - 148px)', overflow: 'auto'}}><Formform={form}name="filterForm"colon={false}hideRequiredMarkstyle={{height: '100%'}}><Form.Itemname="departmentId"label={<div>部门域&nbsp;<Tooltiptitle={<span style={{color: "#3F81EE"}}>打标签规则:选择“四级目录”(一般指二级部门)进行标注,如果没有四级目录则选择最深的一级目录标注。</span>}><InfoCircleOutlined/></Tooltip></div>}rules={[{required: true, message: '请选择资产标记-部门域'}]}><ViCascaderoptions={departmentIds}placeholder="请选择资产标记-部门域"fieldNames={{label: 'name', value: 'id'}}showSearch={{filter}}style={{width: 500}}allowClearchangeOnSelect/></Form.Item></Form></div>)

参考

Cascader级联选择

一种级联前后端实现方案相关推荐

  1. 【开源】分享一个前后端分离方案-前端angularjs+requirejs+dhtmlx 后端asp.net webapi

    一.前言 半年前左右折腾了一个前后端分离的架子,这几天才想起来翻出来分享给大家.关于前后端分离这个话题大家也谈了很久了,希望我这个实践能对大家有点点帮助,演示和源码都贴在后面. 二.技术架构 这两年a ...

  2. Asp.Net统一前后端提示信息方案

    目录 要解决的问题 自定义XML 前端弹框的实现 后端弹框的实现 扩展和整合 示例代码(不完整)及示例截图 示例下载 要解决的问题 减少弹框前后端代码量 增强可维护性 前后端提示资源统一 可以实现简单 ...

  3. 一个简单粗暴的前后端分离方案

    项目背景 刚刚参加完一个项目,背景:后端是用java,后端服务已经开发的差不多了,现在要通过web的方式对外提供服务,也就是B/S架构.后端专注做业务逻辑,不想在后端做页面渲染的事情,只向前端提供数据 ...

  4. 【VUE】vue实现登录滑动拼图验证的两种方法,纯前端组件验证以及前后端同时验证

    vue实现登录滑动拼图验证的两种方法: 第一种是纯前端组件验证,只能区分是人为操作还是机器操作. 第二种是前后端同时验证,这种方法加上后端校验相对会更安全一些.(注:在最底部加上了同时兼容移动端的方法 ...

  5. 移动端开发者眼中的前端开发流程变迁与前后端分离

    写在最开始 这是一篇面向移动端开发者的科普性文章,从前端开发的最初流程开始,结合示范代码,讨论开发流程的演变过程,希望能覆盖一部分前端开发技术栈,从而对前端开发的相关概念形成初步的认识. 本文会提供一 ...

  6. Web系统开发构架再思考-前后端的完全分离

    前言 前后端完全分离其实一直是Web开发人员的梦想,也一直是我的梦想,遥想当年,无论是直接在代码里面输出HTML,还是在HTML里面嵌入各种代码,都不能让人感到满意.期间的痛苦和纠结,我想所有Web开 ...

  7. 前后端分离的思考与实践

    前言 为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异.痛定思痛,今天我们重新思考了"前后端"的定义,引入前端同学都熟悉 ...

  8. 前后端分手大师——MVVM 模式

    阅读目录 简而言之 组成部分 没有什么是一个栗子不能解决的 简而言之 之前对 MVVM 模式一直只是模模糊糊的认识,正所谓没有实践就没有发言权,通过这两年对 Vue 框架的深入学习和项目实践,终于可以 ...

  9. Web系统开发构架再思考-前后端的完全分离 MVVM

    前言 前后端完全分离其实一直是Web开发人员的梦想,也一直是我的梦想,遥想当年,无论是直接在代码里面输出HTML,还是在HTML里面嵌入各种代码,都不能让人感到满意.期间的痛苦和纠结,我想所有Web开 ...

最新文章

  1. 《京东技术解密》读后感
  2. Spring MVC 概述
  3. 我的程序跑了60多小时,就是为了让你看一眼JDK的BUG导致的内存泄漏。
  4. ecshop 收货人信息电话必填改为手机必填
  5. Java 并发编程小册整理好了
  6. java adt入门教程_【教程】【多图详解】如何在Eclipse中离线安装ADT(Android Development Tools)...
  7. java数组给名字排序_用Java给数组排序
  8. 【分享】regsvr32 不是内部或外部命令,也不是可运行的程序或批处理文件
  9. Java 实现 植物大战僵尸 小游戏【附源码】
  10. 基于php的超市仓库管理系统
  11. System x 服务器制作ServerGuide U盘安装Windows Server 2003 操作系统
  12. 给大家推荐一波Python书单,电子版拿走不谢
  13. MinDoc v0.4 发布 轻量级文档在线管理系统
  14. Windows初级运维(一)文件查找DOS命令大全
  15. systemverilog:always_comb、always_latch、always_ff区别
  16. 电脑打印机老是文档挂起无法打印怎么办
  17. 操作系统春招面试复习之:操作系统概述
  18. 淘宝购物如何找优惠券_淘宝上买衣服怎么省钱
  19. 用Python如何开发Excel宏脚本?新手必学
  20. TS: 无法找到模块“xxxx”的声明文件。

热门文章

  1. irc php,IRC / 实时聊天系统
  2. 跨次元!目标检测类别超20000!
  3. 【Android】Activity详解
  4. 入职国企外包第一个星期,实感
  5. 如何修改需要以管理员身份才能操作的文件(极其简单的技巧)
  6. windows编程中ULONG_PTR和指针的互相转换
  7. line-height属性与font-size属性的关系
  8. Openstack基础架构
  9. VUE项目的e2e自动化测试超详细安装过程(保姆级)
  10. struct 结构体中字符串数组赋值的问题