react-添加页面容器

效果

在这里插入图片描述

1. index.ts


import { useEffect, useState } from 'react';
import style from './index.less'
import { history } from 'umi';


interface Props {
  children: any
  route: any
  location: any
}

/**
 * 路由信息
 */
interface RouteInfo {
  // 路由路径
  path: string,

  // 路由名称
  name: string,

}

/**
 * 页面容器
 */
export default (props: Props) => {
  // 全部路由数据
  const [routeList, setRouteList] = useState<RouteInfo[]>([])
  // 当前选中的路由
  const [checkRouteList, setCheckRouteList] = useState<RouteInfo[]>([])
  // 当前选中的路径
  const [currentPath, setCurrentPath] = useState<string>('')

  // 获取路由全部数据
  useEffect(() => {
    let routeList: any = []
    recurGetRoutes(props.route, routeList)
    setRouteList(routeList)
  }, [])
  let pathName = props.location.pathname
  /**
   * 当路由数据加载完毕后,如果当前路径和当前所在路由不同,则需要判断是否已经push到选中的路由中。
   * 如果已经选中则不需要重复push。
   */
  if (routeList?.length) {
    if (currentPath !== pathName) {
      setCurrentPath(pathName)
      if (!checkRouteList.some(item => item.path === pathName)) {
        let currentRoutes: RouteInfo[] = routeList.filter(item => item.path === pathName)
        if (currentRoutes?.length) {
          checkRouteList.push(currentRoutes[0])
        }
      }
    }
  }

  return <>
    <div style={{
      margin: 10
    }}>
      <div
        style={{
          display: 'flex'
        }}
      >
        {
          checkRouteList.map(item => {
            return <TitleBar routeInfo={item}
              activePath={currentPath}
              onContextMenu={function (path: string): void {
                debugger
              }}
              onClick={function (path: string): void {
                // 设置当前路径
                setCurrentPath(path)
                history.push(path)
              }} onClose={function (path: string): void {
                // 删除当前路径
                let residualRouteList = checkRouteList.filter(item => item.path !== path)
                setCheckRouteList(residualRouteList)
                // 如果选中的路由不存在则回到首页
                if (residualRouteList?.length) {
                  history.push(residualRouteList[0].path)
                } else {
                  history.push('/')
                }
              }} />
          })
        }

      </div>
      {props.children}

    </div>


  </>
};

/**
 * 递归获取路由对象中的路径及名称
 * @param route 路由对象
 * @param routeList 路由集合
 */
function recurGetRoutes(route: any, routeList: any[]) {
  route?.children?.forEach((item: any) => {
    routeList.push({
      path: item.path,
      name: item.name
    })
    recurGetRoutes(item, routeList)
  })
}

function TitleBar(props: {
  // 路由信息
  routeInfo: RouteInfo,
  // 点击事件
  onClick: (path: string) => void,
  // 关闭事件
  onClose: (path: string) => void,
  // 右键菜单事件
  onContextMenu: (path: string) => void,
  // 是否选中
  activePath: string,
}) {

  return <>
    <>
      <div className={style['background-color-white'] + (props.activePath === props.routeInfo.path ? ' ' + style['background-color-theme'] : '')} style={{
        borderTopLeftRadius: '10px',
        borderTopRightRadius: '10px',
        width: 150,
        height: 40,
        position: 'relative',
      }}>
        <div
          onClick={() => {
            props.onClick(props.routeInfo.path)
          }}
          onContextMenu={(event) => {
            event.preventDefault()
            props.onContextMenu(props.routeInfo.path)
          }}
          style={{
            textAlign: 'center',
            verticalAlign: 'middle',
            lineHeight: '42px'
          }}>
          <span className={style['cursor-pointer']}
            style={{ color: 'gray' }}
          >{props.routeInfo.name}</span>
        </div>

        <svg className={style.magnify} onClick={() => {
          props.onClose(props.routeInfo.path)
        }} style={{
          position: 'absolute',
          right: '8px',
          top: '5px',
          color: 'gray'
        }}
          viewBox="64 64 896 896" focusable="false" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path></svg>
      </div>
    </>
  </>

}

2. index.less

:hover.magnify {
  transform: scale(1.2);
  cursor: pointer;
}

:hover.cursor-pointer {
  cursor: pointer;
}

:hover.cursor-pointer {
  cursor: pointer;
}

.background-color-white {
  background-color: white;
}

.background-color-theme {
  background-color: #001529;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值