日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

react重新渲染菜单_React实现递归组件

發(fā)布時間:2023/12/2 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 react重新渲染菜单_React实现递归组件 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

今天來實現(xiàn)一個?React?的遞歸組件。具體的效果圖如下:

圖片說明

假設后端返回的數(shù)據(jù)如下:

[{ id: 1, parent_id: 0, name: '廣東省', children: [{ id: 2, parent_id: 1, name: '廣州市', children: [{ id: 3, parent_id: 2, name: '番禺區(qū)' }, { id: 4, parent_id: 2, name: '天河區(qū)' }], }, { id: 7, parent_id: 1, name: '深圳市', children: [{ id: 8, parent_id: 7, name: '南山區(qū)' }, { id: 9, parent_id: 7, name: '寶安區(qū)' }, { id: 10, parent_id: 7, name: '龍崗區(qū)' }, { id: 11, parent_id: 7, name: '龍華區(qū)' }, ], }, ], }, { id: 56, parent_id: 0, name: '廣西省', children: [{ id: 57, parent_id: 56, name: '南寧市' }, ], },]

分析

需求

?每層元素都有一個children屬性,選中這項后展示這一項所有的子菜單,首次展示或者切換時默認展示第一項子菜單?選中時高亮樣式,默認為第一項高亮

實現(xiàn)思路

?每一層的顯示邏輯應該是一樣的,都是渲染這一層的列表即可?對于子菜單的渲染邏輯也類似,如果當前項有?children?屬性,遞歸調(diào)用即可?高亮樣式的邏輯:?用一個路徑數(shù)組記錄好當前渲染的路徑,如果某一項的?id?在數(shù)組里,則高亮?切換父項時,重置數(shù)組中子項的?id?,這里可以用一個深度變量?dep?來控制

實現(xiàn)

渲染

?使用假數(shù)據(jù)來模擬,格式如上述?App.js中傳入的dep是0,后面每渲染一層依次加1即可?每一層初始渲染時默認將第一項作為高亮節(jié)點填入路徑數(shù)組中,路徑數(shù)組具體如何操作在下面

//App.jsimport menuList from './mock/menu'//......this.state = { activePath: []}//......componentDidMount() { let { id } = this.props.list[0] let { dep, activePath } = this.props if (!activePath[dep]) { this.props.changeActivePath(dep, id, this.props.list) }}render() { return ( list={menuList} dep={0} //以下兩個prop來控制高亮邏輯 activePath={this.state.activePath} changeActivePath={this.changeActivePath.bind(this)} /> )}

?此處為渲染一層的邏輯,拿到這一層的數(shù)據(jù)后循環(huán)渲染一下即可?標紅的樣式控制用上面說的路徑數(shù)組來控制

//Menu.jsrender() { let { list, dep } = this.props, renderList = list return ( className="list"> {renderList.map(item => { return <li id={item.id} onClick={this.clickItem.bind(this, item.id)} className={this.props.activePath.includes(item.id) ? 'active' : ''} key={item.id}>{item.name} })} {this.renderMore(list, dep)} )}

下面是渲染子節(jié)點的邏輯:

?先找出當前高亮的節(jié)點,要渲染它的子節(jié)點?遞歸調(diào)用我們的?Menu?組件即可,注意層級加1

renderMore(list, dep) { let moreList = [], id for (let i = 0; i < list.length; i++) { //找出當前高亮的節(jié)點 if (list[i].id == this.props.activePath[this.props.dep]) { moreList = list[i].children id = list[i].id break; } } if (Array.isArray(moreList) && moreList.length > 0) { return ( list={moreList} dep={dep + 1} activePath={this.props.activePath} changeActivePath={this.props.changeActivePath.bind(this)} /> ) }}

切換

?切換的邏輯十分簡單,將點擊的id傳入即可?下面具體來看路徑數(shù)組的處理

clickItem(id) { this.props.changeActivePath(this.props.dep, id, this.props.list)}

處理高亮邏輯

?如果是最后一層,則直接加入即可?如果不是,則將當前層點擊的節(jié)點填入數(shù)組,重新構(gòu)建下面的子節(jié)點?遞歸處理下子節(jié)點,默認是采用第一項作為高亮的節(jié)點

//App.jschangeActivePath(dep, id, list) { let activePath = this.state.activePath if (!activePath[dep] || dep == activePath.length - 1) { //最后一個 添進去即可 activePath[dep] = id } else { //重新構(gòu)建整個activePath數(shù)組 activePath[dep] = id let cur = [] for (let i = 0; i < list.length; i++) { let itemId = list[i].id if (itemId == id) { cur = list[i] break } } setPath(dep + 1, cur) } function setPath(dep, cur) { if (cur.children) { activePath[dep] = cur.children[0].id setPath(dep + 1, cur.children[0]) } } this.setState({ activePath })}

完整代碼

App.js

import React from 'react'import Menu from './components/Menu'import menuList from './mock/menu'class App extends React.Component { constructor(props) { super(props) this.state = { activePath: [] } } render() { return ( list={menuList} dep={0} activePath={this.state.activePath} changeActivePath={this.changeActivePath.bind(this)} /> ) } changeActivePath(dep, id, list) { let activePath = this.state.activePath if (!activePath[dep] || dep == activePath.length - 1) { //最后一個 添進去即可 activePath[dep] = id } else { //重新構(gòu)建整個activePath數(shù)組 activePath[dep] = id let cur = [] for (let i = 0; i < list.length; i++) { let itemId = list[i].id if (itemId == id) { cur = list[i] break } } setPath(dep + 1, cur) } function setPath(dep, cur) { if (cur.children) { activePath[dep] = cur.children[0].id setPath(dep + 1, cur.children[0]) } } this.setState({ activePath }) }}export default App

Menu.js

import React, { Component } from 'react'import '../style/Menu.less'class Menu extends Component { constructor(props) { super(props) } componentDidMount() { let { id } = this.props.list[0] let { dep, activePath } = this.props if (!activePath[dep]) { this.props.changeActivePath(dep, id, this.props.list) } } renderMore(list, dep) { let moreList = [], id for (let i = 0; i < list.length; i++) { if (list[i].id == this.props.activePath[this.props.dep]) { moreList = list[i].children id = list[i].id break; } } if (Array.isArray(moreList) && moreList.length > 0) { return ( list={moreList} dep={dep + 1} activePath={this.props.activePath} changeActivePath={this.props.changeActivePath.bind(this)} /> ) } } clickItem(id) { this.props.changeActivePath(this.props.dep, id, this.props.list) } render() { let { list, dep } = this.props, renderList = list return ( className="list"> {renderList.map(item => { return <li id={item.id} onClick={this.clickItem.bind(this, item.id)} className={this.props.activePath.includes(item.id) ? 'active' : ''} key={item.id}>{item.name} })} {this.renderMore(list, dep)} ) }}export default Menu

Menu.less

ul,li { list-style: none; margin: 0; padding: 0;}.list { display: flex; li { margin: 10px; cursor: pointer; }}.active { color: red;}

總結(jié)

以上是生活随笔為你收集整理的react重新渲染菜单_React实现递归组件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。