React18-树形菜单-递归

这篇具有很好参考价值的文章主要介绍了React18-树形菜单-递归。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

案例分析

https://github.com/dL-hx/manager-fe/commit/85faf3b1ae9a925513583feb02b9a1c87fb462f7

从接口获取城市数据,渲染出一个树形菜单
要求:
可以展开和收起

技巧

  1. 学会递归渲染出一个树形菜单, 并点击后可以展开和收起
  2. 通过对数据上添加控制字段(show)避免在子组件添加各种同步的useState,等字段.保证单向数据流向, 来简化问题.

通信

父子通信

展示效果

React18-树形菜单-递归,项目实战,Vue-React组件设计,前端,前端框架

实现代码

React18-树形菜单-递归,项目实战,Vue-React组件设计,前端,前端框架
React18-树形菜单-递归,项目实战,Vue-React组件设计,前端,前端框架
src\views\TreeMenu\index.tsx

import TreeMenu from "./TreeMenu";
export default TreeMenu

技巧点

  1. 调用pulic/citydata.json数据
  2. 通过原数据添加show字段,递归处理.为每一个item添加show字段
  3. 当再次点击item选项时候,根据原数据上的show字段进行控制, 递归修改源数据对应的id(判断条件找到对应item, if (item.value === id) ).
    将其取反后setData
    对于接口源数据没有返回的ui控制字段,前端需要自己添加

因为是react, 对引用数据修改要注意需要生成新数据后在setData
src\views\TreeMenu\TreeMenu.tsx

import { Button } from "antd";
import { useState, useEffect } from "react";
import Tree from "./Tree";
export default function TreeMenu() {
    const [data, setData] = useState([])

    useEffect(() => {
        fetch('/citydata.json').then(res => res.json()).then(res => {
            setData(recursionAddProps(res))
        })
    }, [])

    // 当数据请求过来后,我们要递归式给每一个数据加一个属性,用来控制是否展开功能
    const recursionAddProps = (data) => {
        // 在item 上加一个属性
        // show: true 则展开,  false 折叠
        return data.map((item) => {
            item.show = false
            // 递归式自己调用自己
            if (item.children) {
                recursionAddProps(item.children)
            }
            return item
        })
    }

    /**
     * 
     * @param data 源数据
     * @param id 点击的id选项
     * @returns 
     */
    const recursionEditProps = (data, id) => {
        // 在item 上加一个属性
        // show: true 则展开,  false 折叠
        return data.map((item) => {
            if (item.value === id) { // 判断条件: 找到对应id在取反
                item.show = !item.show // 取反
            } 
            // 递归式自己调用自己
            if (item.children) {
                recursionEditProps(item.children, id)
            }
            return item
        })
    }

    // 获取到子组件传递过来的数据
    const setShow = (child) => {
        // item.show = true
        // const newData = data.map((item) => {
        //     if (item['value'] === child.value) {
        //         // @ts-ignore
        //         item['show'] = !child.show
        //     }
        //     return item
        // })
        // setData(newData)

        // 需要递归处理这个show展开 
        // console.log(recursionEditProps(data, child.value));
        // 通过item-id,把数据中的show 改为true
        setData(recursionEditProps(data, child.value))
    }
    return <div>
        <Tree data={data} setShow={setShow}></Tree>
    </div>
}

技巧点

  1. 递归调用自身
  2. 通过为父组件原数据添加show字段, 子组件修改父组件数据结构的show字段来控制,子组件是否展示
    因为是单向数据流, 数据控制视图, 通过递归完成

src\views\TreeMenu\Tree.tsx

import Tree from './Tree'

export default ({ data, show=true, setShow }: any) => {
    console.log(data);

    return <ul style={{display: show? 'block': 'none'}}>
        {
            Array.isArray(data) && data.length && data.map(item => {
                return <li key={item.value} onClick={(event)=>{
                    // 清除冒泡
                    event.stopPropagation()
                    setShow(item)
                }}>
                    {item.value}
                    {/* 递归组件 */}
                    {
                        item.children && item.children.length && <Tree data={item.children} show={item.show} setShow={setShow}/>
                    }
                </li>
            })
        }
    </ul>
}

/public/citydata.json

[
    {
        "lable": "北京市",
        "value": "北京市",
        "children": [
            {
                "lable": "东城区",
                "value": "东城区",
                "children": [
                    {
                        "lable": "东城区-0",
                        "value": "东城区-0"
                    },
                    {
                        "lable": "东城区-1",
                        "value": "东城区-1"
                    },
                    {
                        "lable": "东城区-2",
                        "value": "东城区-2"
                    }
                ]
            },
            {
                "lable": "西城区-1",
                "value": "西城区",
                "children": [
                    {
                        "lable": "西城区-0",
                        "value": "西城区-0"
                    },
                    {
                        "lable": "西城区-1",
                        "value": "西城区-1"
                    },
                    {
                        "lable": "西城区-2",
                        "value": "西城区-2"
                    }
                ]
            },
            {
                "lable": "海淀区-2",
                "value": "海淀区-2"
            }
        ]
    },
    {
        "lable": "西安市",
        "value": "西安市",
        "children": [
            {
                "lable": "长安区-0",
                "value": "长安区-0"
            },
            {
                "lable": "桥西区-1",
                "value": "桥西区-1"
            },
            {
                "lable": "新华区-2",
                "value": "新华区-2"
            }
        ]
    },
    {
        "lable": "天津市",
        "value": "天津市"
    }
]

Refer to

https://www.bilibili.com/video/BV19W4y1p7eu文章来源地址https://www.toymoban.com/news/detail-813300.html

到了这里,关于React18-树形菜单-递归的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue3:Elemenu-Plus递归型菜单组件封装(2)

            在上一篇文章中,以Vue2的选项式 API风格,封装了递归型菜单组件,但是这其中存在着一些问题,例如:         【1】子组件menuList.vue中,通过this.$emit()方式定义的事件,在Vue3组合式API风格父组件中可能会被执行多次。之所以说是可能,是因为我这测试中确实遇

    2024年02月13日
    浏览(37)
  • React18从入门到实战

    创建react项目的更多方式 使用 npx react-create-app react-basic项目名称 创建 启动项目 打包项目 启动测试运行项目 将项目中隐藏的webpack配置释放出 以上就是package文件中存放项目核心包的地方 这个地方是项目中可执行的一些命令 将其中除去index.js和app.js的文件全部删掉并分别进入

    2024年04月11日
    浏览(24)
  • qiankun:react18主应用 + 微应用 react18 + vue3

    一:主应用 搭建react项目 安装Antd 在 index.js中引入 安装react-router : 在 index.js中引入 安装 qiankun : 在主应用中注册微应用,在 index.js中引入 注:子应用嵌入到主应用的地方,id要跟index.js下registerMicroApps里面的container设置一致 修改App.js文件,将如下代码放入App.js 修改App.css样

    2024年02月16日
    浏览(30)
  • React18入门(第二篇)——React18+Ts项目配置husky、eslint、pretttier、commitLint

    我的项目版本如下: React: V18.2.0 Node.js: V16.14.0 TypeScript:最新版 工具: VsCode 本文将采用图文详解的方式,手把手带你快速完成在React项目中配置husky、prettier、commitLint,实现编码规范的统一,git提交规范的统一。 1.1 装包 1.2 ESLint 插件安装 1.3 创建命令并使用 新增命令 执行

    2024年02月08日
    浏览(49)
  • 使用React18+Ts创建项目

    首先,使用create-react-app工具创建一个新的React项目: 使用脚手架创建项目后,自带react-dom等依赖项,但react中的所用的路由方法是react-router-dom中。 默认情况下,create-react-app模板会自动生成一些文件和文件夹,这些文件和文件夹包括: node_modules:存储所有的项目依赖项。 p

    2024年02月09日
    浏览(32)
  • 创建react脚手架项目——demo(react18 + react-router 6)+ react项目打包部署

    全局安装 create-react-app 说明:不建议安装全局,建议使用 npx 命令安装,具体可参考官网,如下: 官网: https://zh-hans.legacy.reactjs.org/docs/create-a-new-react-app.html. 1.2.1 问题1——npm ERR! code ENOTFOUND(网络问题clashx) 问题描述,如下: 解决问题——方式1 如果使用了clashx,可能是它

    2024年02月07日
    浏览(51)
  • React18TS项目:配置react-css-modules,使用styleName

    他的好处不说了 网上一堆文章一个能打的都没有, 添加开发依赖 Babel Plugin \\\"React CSS Modules\\\" | Dr. Pogodin Studio 看@dr.pogodin/babel-plugin-react-css-modules官方文档 不使用babel-plugin-react-css-modules 手搭webpack配置需要处理 1.能启用css modules 对于裸 Webpack,请参见webpack css-loader的 modules 的选项

    2024年02月12日
    浏览(34)
  • 使用Mybatis生成树形菜单-适用于各种树形场景

    开发中我们难免会遇到各种树形结构展示的场景。比如用户登录系统后菜单的展示,某些大型购物网站商品的分类展示等等,反正开发中会遇到各种树形展示的功能,这些功能大概处理的思路都是一样的,所以本文就总结一下树形结构的代码生成,在开发的时候套用这种结构

    2024年02月08日
    浏览(28)
  • layui树形菜单的实现

    继续上一篇博客的内容,在原来代码的基础上实现树形菜单功能 在layui中,树形菜单是通过 Tree 组件实现的。Tree 组件提供了一种树形结构展示数据的方式,常用于显示层级结构的菜单、目录等。开发者可以通过配置项和方法对树形菜单进行定制和操作。 树形菜单是一种常见

    2024年02月15日
    浏览(40)
  • Vue实战【调整Vue-element-admin中的菜单栏,并添加顶部模块菜单栏】

    因为最近在整合公司的项目,需要把所有系统里的功能集成到一个项目里,这样就导致菜单栏目录会特别的多,不便于用户使用,体验效果极差。于是想到了一个方法,就是增加顶部导航栏,点击的时候让侧边菜单栏在显示相对应模块的所有菜单;这样的话就可以很大程度提

    2024年01月16日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包