前提:数据结构为树形结构(二级数据带一级ID)

功能说明:默认展示一级下拉菜单,选完一级之后,二级的列表数据为选好的所有一级的二级数据,最后点确定之后,展示全部的选择(包括一级和二级)。展示出来的部分可以删除及全部删除。

!!!注意注意:选了一级,没选择二级,会在最后点确定的时候带出全部的二级,如果这个一级下面选了二级,最后只会展示已选择的二级

你需要准备的变量
  const [cascadeData, setCascadeData] = useState([] as any[]);// 品类的全部数据const [cascadeId, setCascadeId] = useState([] as string[]);// 选定的全部品类const [cascadeVisible, setCascadeVisible] = useState(false);// 一级品类const [secondVisible, setSecondVisible] = useState(false);// 二级品类const [secondLevel, setSecondLevel] = useState([]as any[]);// 二级列表const [selectCategory, setSelectCategory] = useState([] as any[]);// 选定的全部品类对象const [selectedFirstObj, setSelectedFirstObj] = useState([] as any[]);// 选定的一级品类const [selectedFirstId, setSelectedFirstId] = useState([] as any[]);// 选定的一级品类idconst [selectedSecondObj, setSelectedSecondObj] = useState([] as any[]);// 选定的二级品类const [selectedSecondId, setSelectedSecondId] = useState([] as any[]);// 选定的二级品类id
页面结构
 <Space><divonClick={() => {setCascadeVisible(true);}}className={style.cascadeBtn}>{selectedFirstId.length ? `已选${selectedFirstId.length}` : '一级品类'} <DownOutline />{/* 一级品类 <DownOutline /> */}</div>{!!secondLevel.length && <divonClick={() => {setSecondVisible(true);}}className={style.cascadeBtn}>{selectedSecondId.length ? `已选${selectedSecondId.length}` : '二级品类'} <DownOutline />{/* 二级品类 <DownOutline /> */}</div>}{!!secondLevel.length && <Buttoncolor="primary"size="mini"onClick={() => handlerSelectLevel()}>确定</Button>}
</Space><span className={`${style.cardLabel} ${style.cardLabelTitle}`}>筛选结果
</span>
{!!cascadeId.length &&<div className={style.categoryItem}><span className={style.cardLabel}>已选品类:</span><Space wrap className={style.categorySpace}>             {selectCategory.map((item)=>(<Tag className={style.categoryTag} key={item.categoryId}>{/* <ForbidFill /> */}<img src={imgDelete} alt="" className={style.categoryTagClose} onClick={() => onClose(item.categoryId)}/>{item.categoryName}</Tag>))}<Button size="mini" color="primary" onClick={clearCategory}>全部取消</Button></Space></div>}
两个弹窗
<Mask
visible={cascadeVisible}
><div className={style.panel}><div className={`${style.content} ${style.columns}`}><div className={style.checkList}><CheckList onChange={setSelectedFirstObj} multiple value={selectedFirstObj}>{ cascadeData.map((category: any) => (<CheckList.Item key={category.categoryId} value={category}>{category.categoryName}</CheckList.Item>))}</CheckList></div></div><div className={style.btns}><div onClick={handlerLevelCancel} className={style.cancelBtn}>取消</div><div onClick={handlerSelectFirst} className={style.confirmBtn}>确定</div></div></div>
</Mask><Maskvisible={secondVisible}
><div className={style.panel}><div className={`${style.content} ${style.columns}`}><div className={style.checkList}><CheckList onChange={setSelectedSecondObj} multiple value={selectedSecondObj}>{ secondLevel.map((item: any) => (<CheckList.Item key={item.categoryId} value={item}>{item.categoryName}</CheckList.Item>))}</CheckList></div> </div><div className={style.btns}><div onClick={handlerLevelCancel} className={style.cancelBtn}>取消</div><div onClick={handlerSelectSecond} className={style.confirmBtn}>确定</div></div></div>
</Mask>
方法
// 关闭品类弹窗const handlerLevelCancel = () => {setCascadeVisible(false);setSecondVisible(false);};// 一级品类确定const handlerSelectFirst = () => {console.log('一级品类,setSelectedFirstObj',selectedFirstObj);const secondData: React.SetStateAction<any[]> = [];const firstId: string[] = [];selectedFirstObj.forEach(item => {firstId.push(item.categoryId);secondData.push(...item.childCategoryList);});console.log('secondData==>',secondData);setSelectedFirstId(firstId);// 已选一级idsetSecondLevel(secondData);handlerLevelCancel();};// 二级品类确定const handlerSelectSecond = () => {console.log('一级品类,setSelectedSecondObj',selectedSecondObj);const secondIds = selectedSecondObj.length ? selectedSecondObj.map((item) => item.categoryId) : [];setSelectedSecondId(secondIds);// 已选二级idhandlerLevelCancel();};// 全部品类的idconst handlerSelectLevel = () => {console.log(selectedFirstObj);console.log(selectedSecondObj);console.log(secondLevel);let firstIds: any[] = [];let secondIds: any[] = [];let childObj: any[] = [];if (selectedFirstObj.length) {firstIds = selectedFirstObj.map(item=>item.categoryId);if (selectedSecondObj.length) {console.log('firstIds==>', firstIds);const pIds = selectedSecondObj.map(item=>item.parentCategoryId);childObj = secondLevel.filter(item=>!pIds.includes(item.parentCategoryId));console.log('childObj===>',childObj);} else {childObj = secondLevel;}secondIds = [...selectedSecondObj, ...childObj].map(item=>item.categoryId);console.log('secondIds===>',secondIds);setSelectedFirstId(firstIds);// 已选一级idsetSelectedSecondId(secondIds);// 已选二级idsetCascadeId([...firstIds, ...secondIds]);// 全部idsetSelectCategory([...selectedFirstObj, ...selectedSecondObj, ...childObj]);// 全部的品类console.log(selectCategory);} else {Toast.show('请选择品类');}};// 去掉已选品类const onClose = (id:string) => {const newCategoryId = cascadeId.filter(item=>item !== id);const newSelectedFirstObj = selectedFirstObj.filter(item => item.categoryId !== id);const firstIds = selectedFirstId.filter(item => item !== id);const newSelectedSecondObj = selectedSecondObj.filter(item => item.categoryId !== id);const secondIds = selectedSecondId.filter(item => item !== id);const newCategoryObj = selectCategory.filter(item => item.categoryId !== id);setCascadeId(newCategoryId);// 全部idsetSelectedFirstObj(newSelectedFirstObj);// 一级对象setSelectedFirstId(firstIds);// 已选一级idsetSelectedSecondObj(newSelectedSecondObj);// 二级对象setSelectedSecondId(secondIds);// 已选二级idsetSelectCategory(newCategoryObj);// 全部的品类};// 取消选择的所有品类const clearCategory = () => {setCascadeId([]);// 全部idsetSelectedFirstObj([]);// 一级对象setSelectedFirstId([]);// 已选一级idsetSelectedSecondObj([]);// 二级对象setSelectedSecondId([]);// 已选二级idsetSelectCategory([]);// 全部的品类setSecondLevel([]);// 全部二级};// 反显已选的品类const categoryShow = () => {if ( cascadeId && cascadeId.length && cascadeData && cascadeData.length) {      const seLevel: any[] = [];let seIds: any[] = [...cascadeId];const firstObj: any[] = [];const firstId: string[] = [];const secondObj: React.SetStateAction<any[]> = [];cascadeData.forEach((item:any) => {if (cascadeId.includes(item.categoryId)) {firstId.push(item.categoryId);firstObj.push(item);seLevel.push(...item.childCategoryList);seIds = seIds.filter(seIns=>seIns !== item.categoryId);}});seLevel.forEach((item:any) => {if (seIds.includes(item.categoryId)) {secondObj.push(item);}});setSelectedFirstObj(firstObj);// 已选一级setSelectedFirstId(firstId);// 已选一级idsetSecondLevel(seLevel);// 全部二级setSelectedSecondObj(secondObj);// 已选二级setSelectedSecondId(seIds);// 已选二级idsetSelectCategory([...firstObj,...secondObj]);// 已选全部}};

移动端 react + antd-mobile 二级联动(一二级均多选)相关推荐

  1. React后台管理系统-品类选择器二级联动组件

    React后台管理系统-品类选择器二级联动组件 品类选择器二级联动 posted on 2018-06-26 22:21 gisery 阅读( ...) 评论( ...) 编辑 收藏

  2. vue一二级联动清空二级数据_【周一实用技巧】二级联动还不够,自动更新才最牛。Excel 2013利用数据验证条件制作一级、二级联动和自动更新下拉列表...

    Excel 2013实用技巧教程系列 第-9.4-节  下拉列表 下拉列表作为提高数据录入效率和防止错误数据的有效方法,在日常工作中应用非常普遍.除了一级.二级联动列表,小编excel小课堂(ID:e ...

  3. React+Antd+TypeScript 开发规范

    React+Antd+TypeScript 规范整合 1.TypeScript代码标准化规则 提取出部分适用于项目中的官方要求的的TypeScript用于约束贡献者的编码规范 [typescript官 ...

  4. antd Mobile Tabs 垂直布局 后台传入数据

    最近两周在研究react 相关项目,react 相关的 UI插件中,antd 算是比较好的一种,所以这里就用antd mobile 开发一个移动端项目.具体react 知识点就不赘述了.这里主要讲遇到 ...

  5. antd mobile v5 它悄悄的来了

    在 React 领域里,一直缺少一套靠谱.好用的移动端组件,蚂蚁的 antd mobile v2 年久失修,几乎无人维护,跟 antd 相差甚远,在设计上,也有很多也已经跟不再符合 Alipay De ...

  6. Antd Mobile Design输入框组件InputItem错误显示方式封装

    antd-mobile默认的是输入框错误处理方式为在输入框右侧显示错误图标,点击图标触发绑定的onErrorClick事件,这样显得不够直观,现想利用现有组件参数对其进行封装,达到在右侧不显示错误图标 ...

  7. dw二级联动下拉菜单插件 宋君墨_Excel下拉菜单不会做?15秒教会你制作一二三级联动下拉菜单,从此做表不求人!...

    Hi,各位叨友们好呀!我是叨叨君~ 我们都知道,在使用Excel表格统计数据的时候,为了方便录入,通常会在Excel中设置下拉菜单,以便我们输入相同的内容. 那么,Excel中一级.二级.三级联动下拉 ...

  8. react+antd搭建后台管理系统

    文章目录 前言 一.效果图 二.框架内容 1.技术栈 2.项目目录 3.setting.js(全局配置文件) 4.跨域代理 5.路由react-router 6.状态管理 react-redux 下载 ...

  9. antd的联级选择器异步调用编辑回显_react-uplod-img 是一个基于 React antd组件的图片上传组件...

    react-uplod-img 是一个基于 React antd组件的图片上传组件 支持oss qiniu等服务端自定义获取签名,批量上传, 预览, 删除, 图片精确的尺寸限制 排序等功能 需要 re ...

最新文章

  1. SAP WMSD集成之Copy WM Quantity – Copy WM qty as delivery qty into delivery and PGI
  2. 解决 Error:No suitable device found: no device found for connection quot;System eth0quot;
  3. 第十天2017/04/21(2、泛型编程:模板 / 全特化、偏特化)
  4. 练习1: Python基本语法元素 (第1周)
  5. linux命令:sosreport
  6. Linux下装完mysql后默认密码是多少
  7. 浮点运算和代码优化, 音频常识, 并行计算
  8. Flex的Array和ArrayCollection
  9. 微信电脑客户端登陆_电脑端的微信只能开一个?简单操作就能随意开
  10. lia人是什么意思_狗狗喜欢舔人到底什么意思?毛孩的心思主人你要懂
  11. C# 依赖注入那些事儿
  12. php blog to explore
  13. html文本改,编辑html格式文本可改成txt格式(可以替换或更换某文本)新手
  14. css html 双面打印_从 Linux 命令行进行打印 | Linux 中国
  15. php jwt怎么保存再客户端,php – 如何将JWT添加到授权标头?
  16. 程序员大保健指南,给自己的身心偶尔放松的机会
  17. 改变this指向的方法
  18. 洛克菲勒写给儿子的38封信
  19. android中服务播放音乐,android中用Service播放音乐
  20. 个人邮箱怎么注册,商业人士用哪个邮箱,邮箱使用全攻略!

热门文章

  1. CodeForces961F- k-substrings(哈希)
  2. Go home or stand up
  3. wordpress谷歌字体_如何在WordPress帖子编辑器中添加Google字体
  4. 2.6.36.2 s3c6410 触摸屏驱动移植。
  5. 车牌识别系统四:Pyqt5编写简易车牌识别界面
  6. 【django】settings.py配置文件内容详细介绍
  7. 英国电信进军中国市场,难对三大运营商造成太大影响
  8. 《数学建模简明教程--基于python》学习笔记-第二章-绘图与解方程组-课后习题解答
  9. java meter_自定义Java Swing Meter控件
  10. java 运行class_运行java的class文件方法详解