3.左侧导航栏

Posted lucy-xyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3.左侧导航栏相关的知识,希望对你有一定的参考价值。

<script>

<Menu
          defaultSelectedKeys={[/home]} //数组类型  让那个key被选中  这个值不应该写死,应该根据路径确定
          defaultOpenKeys={[sub1]}
          mode="inline"  //菜单下拉方式  vertival
          theme="dark"
          inlineCollapsed={this.state.collapsed}
        >
     
    <Menu.Item key="/home">
            <Link to="/home">
              <Icon type="home" />
              <span>首页</span>
            </Link>
          </Menu.Item>

          <SubMenu
            key="pro"
            title={
              <span>
                <Icon type="mail" />
                <span>商品</span>
              </span>
            }
          >
            <Menu.Item key="/category">
              <Link to="/category">
                <Icon type="folder-open" />
                <span>品类管理</span>
              </Link>
            </Menu.Item>
            <Menu.Item key="/products">
              <Link to="/products">
                <Icon type="filter" />
                <span>商品管理</span>
              </Link>
            </Menu.Item>
          </SubMenu>
        </Menu>
 
</script>

每个menu都对应一个路由,所以配对的时候用路径

Menu.Item里的key就用路径来匹配  因为是唯一的

点击menu.item里的内容应该进行路由的跳转   所以用Link包裹起来

 

优化:不够灵活

一个菜单主要包含图标和文字和key   导航列表应该设置成为一个配置

 

src/config/menuConfig.js

<script>
const menuList = [
  {
    title: 首页, // 菜单标题名称
    key: /home, // 对应的path
    icon: home, // 图标名称
    public: true, // 公开的
  },
  {
    title: 商品,
    key: /products,
    icon: appstore,
    children: [ // 子菜单列表
      {
        title: 品类管理,
        key: /category,
        icon: bars
      },
      {
        title: 商品管理,
        key: /product,
        icon: tool
      },
    ]
  },

  {
    title: 用户管理,
    key: /user,
    icon: user
  },
  {
    title: 角色管理,
    key: /role,
    icon: safety,
  },

  {
    title: 图形图表,
    key: /charts,
    icon: area-chart,
    children: [
      {
        title: 柱形图,
        key: /charts/bar,
        icon: bar-chart
      },
      {
        title: 折线图,
        key: /charts/line,
        icon: line-chart
      },
      {
        title: 饼图,
        key: /charts/pie,
        icon: pie-chart
      },
    ]
  },
]

export default menuList
</script>

根据menuList生成标签类型,把menu里的内容显示出来

根据数组数据生成标签数组

 {menuList.map(item=>(
            <Menu.Item key={item.key}>
            <Link to={item.key}>
              <Icon type={item.icon} />
              <span>{item.title}</span>
            </Link>
          </Menu.Item>
          ))}
<script> 
//根据指定menu数据数组生成<Menu.Item>和SubMenu的数组
  //map+函数递归
  renderMenu = (menuList) => {
    return menuList.map(item => {
      if (!item.children) {
        return (<Menu.Item key={item.key}>
          <Link to={item.key}>
            <Icon type={item.icon} />
            <span>{item.title}</span>
          </Link>
        </Menu.Item>
        )
      } 
      return(
        <SubMenu
        key={item.key}
        title={
          <span>
            <Icon type={item.icon} />
            <span>{item.title}</span>
          </span>
        }
      >
        {this.renderMenu2(item.children)}
      </SubMenu>
      )
    })
  }

  render() {
    return (
      <div className={styles.leftNav}>
        <header>
          <Link to="/" >
            后台系统
          </Link>
        </header>
        <Menu
          defaultSelectedKeys={[/home]}
          // defaultOpenKeys={[‘sub1‘]}
          mode="inline"
          theme="dark"
          inlineCollapsed={this.state.collapsed}
        >

      {this.renderMenu(menuList)}
 </Menu>
      </div>
    );
  }
}
</script/>

 

 
 
用reduce方法实现menu
 
 
  //根据指定menu数据数组生成<Menu.Item>和SubMenu的数组
  // reduce+函数递归
  renderMenu2=(menuList)=>{
    //求奇数和
    const arr1=[1,2,3,4]
    arr1.reduce((preTotal,item)=>{
      // return preTotal + item //这样是所有元素的和  必须把当此统计的结果return  变为下次统计的初始值
      return proTotal + (item%2===1?item:0)  //返回奇数和  这个是便利回调函数:统计:必须返回当此统计的结果
    },0)  //0代表的初始总和
  }

 

<script>
  renderMenu2=(menuList)=>{
    // //求奇数和
    // const arr1=[1,2,3,4]
    // arr1.reduce((preTotal,item)=>{
    //   // return preTotal + item //这样是所有元素的和  必须把当此统计的结果return  变为下次统计的初始值
    //   return proTotal + (item%2===1?item:0)  //返回奇数和  这个是便利回调函数:统计:必须返回当此统计的结果
    // },0)  //0代表的初始总和

    return menuList.reduce((pre,item)=>{
      //可能向pre添加<Menu.Item></Menu.Item>
      if(!item.children){
        pre.push(<Menu.Item key={item.key}>
          <Link to={item.key}>
            <Icon type={item.icon} />
            <span>{item.title}</span>
          </Link>
        </Menu.Item>)
      }else{
        pre.push(  <SubMenu
          key={item.key}
          title={
            <span>
              <Icon type={item.icon} />
              <span>{item.title}</span>
            </span>
          }
        >
          {this.renderMenu2(item.children)}
        </SubMenu>)
      }
      //可能是SubMenu
      return pre
    },[])
  }
</script>

 

路由器有个模块组件叫withRouter   可以让组件获得路由方法

<script>
import { Link,withRouter } from react-router-dom

const { SubMenu } = Menu;

class leftNav extends Component {

  state = {
 
}

//向外暴露,使用高阶组件withRouter()来包装非路由组件
//新组件向LeftNav传递3个特别属性:history/location/match
//结果:leftNav可以操作路由相关语法了
export default withRouter(leftNav)
</script>
<Menu
          defaultSelectedKeys={[‘/home‘]} //数组类型  让那个key被选中  这个值不应该写死,应该根据路径确定
 //得到当前请求的路由路径:这个是路由的能力
    const selectKey = this.props.location.pathname  //但是this.props.location是undefied  props里没有location
    //这是个非路由组件,所以没有history,location  但我们需要路由里面的属性
    //这时候路由组件提供了withRouter 
 
<script>
//让子菜单能自动选中

renderMenu2=(menuList)=>{


    const path = this.props.location.pathname
    return menuList.reduce((pre,item)=>{
      //可能向pre添加<Menu.Item></Menu.Item>
      if(!item.children){
        pre.push(<Menu.Item key={item.key}>
          <Link to={item.key}>
            <Icon type={item.icon} />
            <span>{item.title}</span>
          </Link>
        </Menu.Item>)
      }else{
        /*
        判断当前item的key是否是我需要的openKey
        查找item的所有children中cItem的key,看是否有一个跟请求的path匹配
        */
       const cItem = item.children.find(cItem=>cItem.key===path)
       if(cItem){
         this.openKey = item.key
       }
        pre.push(  <SubMenu
          key={item.key}
          title={
            <span>
              <Icon type={item.icon} />
              <span>{item.title}</span>
            </span>
          }
        >
          {this.renderMenu2(item.children)}
        </SubMenu>)
      }
      //可能是SubMenu
      return pre
    },[])
  }
 render() {

    //因为下方的this.openKey会拿不到值,因该先把子组件渲染出来拿到openKey
    const menuNode = this.renderMenu2(menuList)

    //得到当前请求的路由路径:这个是路由的能力
    const selectKey = this.props.location.pathname  //但是this.props.location是undefied  props里没有location
    //这是个非路由组件,所以没有history,location  但我们需要路由里面的属性
    //这时候路由组件提供了withRouter 

    return (
      <div className={styles.leftNav}>
        <header>
          <Link to="/" >
            后台系统
          </Link>
        </header>
        <Menu
          defaultSelectedKeys={[selectKey]} //这个值应该根据路径进行变化,而不是固定的
          defaultOpenKeys={[this.openKey]}  //没有这个的时候,路径为子菜单的时候,不会展开,看不到,需要请求到子路由的时候让他自动展开
          mode="inline"
          theme="dark"
          inlineCollapsed={this.state.collapsed}
        >

      {menuNode}
</Menu>
</div>






</script>

 

 优化:从login进入admin会进行两次render

理由是:login页面点击登陆后使用了this.props.history.replace进行跳转进入‘/ ’,这时候LeftNav组件进行第一次渲染,然后进入Content组件,遇到<Redirect to="/home" />又进行匹配 进行跳转

这个时候其实要进入App.js里进行匹配,App.js只有‘/login‘ 和 ’/ ‘  ,其实进行的是模糊匹配   ’/home‘匹配不到login就会去匹配 ‘/ ‘

要设置成精确匹配  使用exact={true}  但是不能使用这个 只用这个 ‘/home‘就匹配不到

  {/**/}

defaultSelectKeys:总是根据据第一次指定的key进行显示

selectedKeys:总是根据最新指定的key进行显示 ;所以用这个

以上是关于3.左侧导航栏的主要内容,如果未能解决你的问题,请参考以下文章

使用底部导航栏防止片段刷新

android 怎么实现左侧导航栏

CSS课程网站 Banner 制作 ② ( Banner 栏版心盒子测量 | Banner 版心盒子模型左侧导航栏代码示例 )

delphi左侧导航栏收缩

通过底部导航栏更改片段时恢复片段状态

在导航栏左侧添加标题