知识点

  • 编写底部导航栏
  • 创建图标公用组件
  • 路由控制底部导航栏的显隐

    编写底部导航栏

    我们先观察我们今天要实现的底部导航长啥样,如下所示:
    image.png
    我们在上一章的代码基础上添加导航栏组件,在 src 目录下新建 components 目录,专门用于放置一些公用组件,我们再在 components 目录下新建 NavBar 目录,用于编写底部导航栏,代码如下所示: ```javascript import React, { useState } from ‘react’; import PropTypes from ‘prop-types’ import { TabBar } from ‘zarm’; import { useHistory } from ‘react-router-dom’; import s from ‘./style.module.less’;

const NavBar = ({ showNav }) => { const [activeKey, setActiveKey] = useState(‘/‘); const history = useHistory()

const changeTab = (path) => { setActiveKey(path) history.push(path) }

return ( ); };

NavBar.propTypes = { showNav: PropTypes.bool }

export default NavBar;

  1. 跳转到对应的组件,'/''/data''/user' 这三个路由对应的三个组件我们还未编写,这里我们在 container 目录下新建这三个页面组件,作为占位。
  2. ```javascript
  3. // Home/index.jsx
  4. import React from 'react'
  5. const Home = () => {
  6. return <div>首页</div>
  7. }
  8. export default Home
  9. // Data/index.jsx
  10. import React from 'react'
  11. const Data = () => {
  12. return <div>数据</div>
  13. }
  14. export default Data
  15. // User/index.jsx
  16. import React from 'react'
  17. const User = () => {
  18. return <div>个人中心</div>
  19. }
  20. export default User

前往 router/index.js 添加路由配置,如果不添加这个配置,调用 history.push 这个方法,就无法匹配到对应的页面组件,代码如下:

  1. // router/index.js
  2. import Home from '@/container/Home'
  3. import Data from '@/container/Data'
  4. import User from '@/container/User'
  5. const routes = [
  6. {
  7. path: "/",
  8. component: Home
  9. },
  10. {
  11. path: "/data",
  12. component: Data
  13. },
  14. {
  15. path: "/user",
  16. component: User
  17. }
  18. ];
  19. export default routes

最后,将导航栏组件引入 App.jsx 入口页面,如下所示:

  1. // App.jsx
  2. ...
  3. import NavBar from '@/components/NavBar';
  4. ...
  5. function App() {
  6. return <Router>
  7. <ConfigProvider primaryColor={'#007fff'}>
  8. <Switch>
  9. {
  10. routes.map(route => <Route exact key={route.path} path={route.path}>
  11. <route.component />
  12. </Route>)
  13. }
  14. </Switch>
  15. </ConfigProvider>
  16. <NavBar showNav={true} />
  17. </Router>
  18. }

浏览器展示效果如下所示:
image.png

添加底部导航图标

我们将图标写成公共组件,这样便于后面各个页面方便引入,我们新建 components/CustomIcon/index.jsx,添加如下代码:

  1. import { Icon } from 'zarm';
  2. export default Icon.createFromIconfont('//at.alicdn.com/t/font_2236655_w1mpqp7n1ni.js');

上述代码,我们引入 Icon,执行它的自定义图标方法 createFromIconfont,它接收一个参数,为 iconfont 生产的静态脚本路径,你可以自己去 官网 配置,也可以直接用我提供的:
image.png
接着我们将其引入到代码中使用,打开 components/NavBar/index.jsx ,添加如下属性:

  1. import CustomIcon from '../CustomIcon';
  2. ...
  3. <TabBar.Item
  4. itemKey="/"
  5. title="账单"
  6. icon={<CustomIcon type="zhangdan" />}
  7. />
  8. <TabBar.Item
  9. itemKey="/data"
  10. title="统计"
  11. icon={<CustomIcon type="tongji" />}
  12. />
  13. <TabBar.Item
  14. itemKey="/user"
  15. title="我的"
  16. icon={<CustomIcon type="wode" />}
  17. />

查看浏览器展示效果如下:
image.png

底部导航栏的显示隐藏

我们在之前引入 NavBar 的代码中,将 showNav 属性写死为 true。此时,我们需要将其盘活,打开 App.jsx,添加如下代码:

  1. import React, { useEffect, useState } from 'react'
  2. import {
  3. BrowserRouter as Router,
  4. Switch,
  5. Route,
  6. useLocation
  7. } from "react-router-dom"
  8. import NavBar from '@/components/NavBar';
  9. import { ConfigProvider } from 'zarm'
  10. import routes from '@/router'
  11. function App() {
  12. const location = useLocation() // 拿到 location 实例
  13. const { pathname } = location // 获取当前路径
  14. const needNav = ['/', '/data', '/user'] // 需要底部导航栏的路径
  15. const [showNav, setShowNav] = useState(false) // 是否展示 Nav
  16. useEffect(() => {
  17. setShowNav(needNav.includes(pathname))
  18. }, [pathname]) // [] 内的参数若是变化,便会执行上述回调函数=
  19. return <Router>
  20. <ConfigProvider primaryColor={'#007fff'}>
  21. <Switch>
  22. {
  23. routes.map(route => <Route exact key={route.path} path={route.path}>
  24. <route.component />
  25. </Route>)
  26. }
  27. </Switch>
  28. </ConfigProvider>
  29. <NavBar showNav={true} />
  30. </Router>
  31. }
  32. export default App

执行 useLocation 时,报错 location of undefined。这是因为想要在函数组件内执行 useLocation,该组件必须被 Router 高阶组件包裹,我们做如下改动,将 App.jsx 的 Router 组件,前移到 main.jsx 内,如下:
image.png
最后,别忘记把组件属性修改成动态变量:

  1. <NavBar showNav={showNav} />

总结

导航栏可以用在很多地方,映射到 PC 网页就是左侧侧边导航,道理都是相通的。移动端放在下面控制,PC 端放在左边或者右边控制罢了。所以再次强调不要学完了一个知识点,就思维定势地认为只能用在某一个需求上,能做到融会贯通,才是判断一个好程序员的标准。