知识点
- 编写底部导航栏
- 创建图标公用组件
- 路由控制底部导航栏的显隐
编写底部导航栏
我们先观察我们今天要实现的底部导航长啥样,如下所示:
我们在上一章的代码基础上添加导航栏组件,在 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;
跳转到对应的组件,'/'、'/data'、'/user' 这三个路由对应的三个组件我们还未编写,这里我们在 container 目录下新建这三个页面组件,作为占位。
```javascript
// Home/index.jsx
import React from 'react'
const Home = () => {
return <div>首页</div>
}
export default Home
// Data/index.jsx
import React from 'react'
const Data = () => {
return <div>数据</div>
}
export default Data
// User/index.jsx
import React from 'react'
const User = () => {
return <div>个人中心</div>
}
export default User
前往 router/index.js 添加路由配置,如果不添加这个配置,调用 history.push 这个方法,就无法匹配到对应的页面组件,代码如下:
// router/index.js
import Home from '@/container/Home'
import Data from '@/container/Data'
import User from '@/container/User'
const routes = [
{
path: "/",
component: Home
},
{
path: "/data",
component: Data
},
{
path: "/user",
component: User
}
];
export default routes
最后,将导航栏组件引入 App.jsx 入口页面,如下所示:
// App.jsx
...
import NavBar from '@/components/NavBar';
...
function App() {
return <Router>
<ConfigProvider primaryColor={'#007fff'}>
<Switch>
{
routes.map(route => <Route exact key={route.path} path={route.path}>
<route.component />
</Route>)
}
</Switch>
</ConfigProvider>
<NavBar showNav={true} />
</Router>
}
添加底部导航图标
我们将图标写成公共组件,这样便于后面各个页面方便引入,我们新建 components/CustomIcon/index.jsx,添加如下代码:
import { Icon } from 'zarm';
export default Icon.createFromIconfont('//at.alicdn.com/t/font_2236655_w1mpqp7n1ni.js');
上述代码,我们引入 Icon,执行它的自定义图标方法 createFromIconfont,它接收一个参数,为 iconfont 生产的静态脚本路径,你可以自己去 官网 配置,也可以直接用我提供的:
接着我们将其引入到代码中使用,打开 components/NavBar/index.jsx ,添加如下属性:
import CustomIcon from '../CustomIcon';
...
<TabBar.Item
itemKey="/"
title="账单"
icon={<CustomIcon type="zhangdan" />}
/>
<TabBar.Item
itemKey="/data"
title="统计"
icon={<CustomIcon type="tongji" />}
/>
<TabBar.Item
itemKey="/user"
title="我的"
icon={<CustomIcon type="wode" />}
/>
底部导航栏的显示隐藏
我们在之前引入 NavBar 的代码中,将 showNav 属性写死为 true。此时,我们需要将其盘活,打开 App.jsx,添加如下代码:
import React, { useEffect, useState } from 'react'
import {
BrowserRouter as Router,
Switch,
Route,
useLocation
} from "react-router-dom"
import NavBar from '@/components/NavBar';
import { ConfigProvider } from 'zarm'
import routes from '@/router'
function App() {
const location = useLocation() // 拿到 location 实例
const { pathname } = location // 获取当前路径
const needNav = ['/', '/data', '/user'] // 需要底部导航栏的路径
const [showNav, setShowNav] = useState(false) // 是否展示 Nav
useEffect(() => {
setShowNav(needNav.includes(pathname))
}, [pathname]) // [] 内的参数若是变化,便会执行上述回调函数=
return <Router>
<ConfigProvider primaryColor={'#007fff'}>
<Switch>
{
routes.map(route => <Route exact key={route.path} path={route.path}>
<route.component />
</Route>)
}
</Switch>
</ConfigProvider>
<NavBar showNav={true} />
</Router>
}
export default App
执行 useLocation 时,报错 location of undefined。这是因为想要在函数组件内执行 useLocation,该组件必须被 Router 高阶组件包裹,我们做如下改动,将 App.jsx 的 Router 组件,前移到 main.jsx 内,如下:
最后,别忘记把组件属性修改成动态变量:
<NavBar showNav={showNav} />
总结
导航栏可以用在很多地方,映射到 PC 网页就是左侧侧边导航,道理都是相通的。移动端放在下面控制,PC 端放在左边或者右边控制罢了。所以再次强调不要学完了一个知识点,就思维定势地认为只能用在某一个需求上,能做到融会贯通,才是判断一个好程序员的标准。