Node + React 实战:从 0 到 1 实现记账本(十一)


theme: channing-cyan

完成底部导航、登陆注册实现

前言

上一章节,从 0 开始搭建出一套以 React 技术栈为基础的前端开发环境,过程中肯定会遇到各奇怪怪的问题,比如 Node 版本问题,工具包的版本问题,插件下载完之后,无法得到自己想要的效果等等,这也是很正常的,所以得耐心百度啊,留言问我也行的。

倘若学会了这一套搭建流程,根据项目需求,灵活的切换组件库、PC 版、甚至是主框架。这对提升自己的知识广度很有帮助,因为相比每次都看教程,自己手动实现一遍,印象会更深刻,遇到问题也能通过自己的认知,去解决它。

话不多说,直接开肝。

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

一.编写底部导航栏

先观察今天要实现的底部导航长啥样,如下所示:

image.png

上图红框中的底部导航栏,在很多业务场景下都是需要的,三个导航栏对应着三个不同的三个页面组件,分别是「账单」、「统计」、「我的」。这三个页面组件是需要导航栏的。如果点击内页如账单详情页,则底部的导航栏会被隐藏,这就需要在导航栏的控制上,下一些功夫。

话不多说,在上一章基础上添加导航栏组件,在 src 目录下新建 components 目录,专门用于放置一些公用组件,再在 components 目录下新建 NavBar 目录,用于编写底部导航栏,代码如下所示:

Nav/index.jsx

```jsx 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 (
    <TabBar visible={showNav} className={s.tab} activeKey={activeKey} onChange={changeTab}>
        <TabBar.Item
            itemKey="/"
            title="账单"
        />
        <TabBar.Item
            itemKey="/data"
            title="统计"
        />
        <TabBar.Item
            itemKey="/user"
            title="我的"
        />
    </TabBar>
);

};

NavBar.propTypes = { showNav: PropTypes.bool }

export default NavBar; ```

代码解析:

首先是声明 NavBar 函数组件,它接收一个外部传入的 showNav 属性,用于控制导航栏的显示隐藏。

通过 useHistory 钩子方法,拿到路由实例 history,它内部含有很多路由的方法,在上述代码中,使用到的是 history.push 进行路由跳转。

在页面中,引入 TabBar 组件,它接受几个属性:

  • visible:用于控制导航栏的显示隐藏。
  • activeKey:当前被点击的导航栏。
  • onChange:点击导航栏之后的回调方法,path 参数为 TabBar.Item 的 itemKey 属性。

TabBar 官方文档: https://zarm.gitee.io/#/components/tab-bar

所以当你点击导航栏的时候,changeTab 方法便会被触发,执行内部的 setActiveKey 和 history.push,他们的作用分别是设置当前点击的高亮和让页面跳转到对应的页面组件。

说到跳转到对应的组件,'/'、'/data'、'/user' 这三个路由对应的三个组件还未编写,这里在 pages 目录下新建这三个页面组件,作为占位。

```jsx // Home/index.jsx import React from 'react'

const Home = () => { return

首页
}

export default Home

// Data/index.jsx import React from 'react'

const Data = () => { return

数据
}

export default Data

// User/index.jsx import React from 'react'

const User = () => { return

个人中心
}

export default User ```

别忘了,前往 router/index.js 添加路由配置,如果不添加这个配置,调用 history.push 这个方法,就无法匹配到对应的页面组件,代码如下: ```js // router/index.js import Home from '@/pages/Home' import Data from '@/pages/Data' import User from '@/pages/User'

const routes = [ { path: "/", component: Home }, { path: "/data", component: Data }, { path: "/user", component: User } ];

export default routes ```

这时,还缺少一步,将导航栏组件引入 App.jsx 入口页面,如下所示:

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> }

通过 npm run dev 启动项目,浏览器展示效果如下所示:

image.png

上图效果所示,注意地址栏的变化,点击相应的 Tab,调用的 history.push 方法,将地址栏的 pathname 改变,随之而来的是页面组件的改变。这个就应证了之前解释的单页面路由控制的原理。history.push 做的事情就是改变地址栏,地址栏一旦改变,就会触发地址所对应的组件渲染,如 /data,渲染的就是 Data 页面组件。

你会问为什么导航栏会一直显示在底部,来分析以下代码:

image.png

红色框是组件展示的区域,每个路径对应着一个组件,这个在 router/index.js 文件中也有所体现。

绿色框则代表导航栏的位置,也就是说,无论上面的组件怎么变化,底部的导航栏一直都是存在的。

二.添加底部导航图标

将图标写成公共组件,这样便于后面各个页面方便引入,新建 components/CustomIcon/index.jsx,添加如下代码: ```js import { Icon } from 'zarm';

export default Icon.createFromIconfont('//at.alicdn.com/t/font2236655w1mpqp7n1ni.js'); ```

上述代码,引入 Icon,执行它的自定义图标方法 createFromIconfont,它接收一个参数,为 iconfont 生产的静态脚本路径,你可以自己去 官网 配置,也可以直接用我提供的:

image.png

里我已经为大家添加好了各个图标,地址就是上述代码的地址。

接着将其引入到代码中使用,打开 components/NavBar/index.jsx ,添加如下属性:

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" />} />

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

image.png

三.底部导航栏的显示隐藏

在之前引入 NavBar 的代码中,将 showNav 属性写死为 true。此时,需要将其盘活,打开 App.jsx,添加如下代码: ```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 { routes.map(route => ) } }

export default App ```

当你刷新浏览器,控制台应该会报下面的错误:

image.png

执行 useLocation 时,报错 location of undefined。这是因为想要在函数组件内执行 useLocation,该组件必须被 Router 高阶组件包裹,做如下改动,将 App.jsx 的 Router 组件,前移到 main.jsx 内,如下:

image.png

逻辑分析:

拿到 pathname,将其设置为 useEffect 钩子函数的第二个参数,监听它的变化,一旦 pathname 变化,便会触发回调函数执行 setShowNav(needNav.includes(pathname)),结果会传递给 NavBar 组件,从而控制组件的显示隐藏。needNav 为需要底部导航的路径值。

不妨做个测试,在 pages 目录下新建一个测试页面组件 Detail,并且添加路由配置。

别忘记把组件属性修改成动态变量: js <NavBar showNav={showNav} />

查看浏览器就没问题了。

实现了底部导航栏,并且创建了三个主页面,这三个页面是需要展示底部导航栏,现在来制作的「登录注册页面」便是不需要底部导航栏的单独页面。

四.注册页面

image.png

系统是面向多用户的,换句话说也就是一个纯正的 C 端项目,任何人都可以通过网站,注册一个新的账号。接下来开始注册页面的编写。

首先新建 Login 文件夹,在文件夹内添加两个文件 index.jsx 和 style.module.less,先把注册页面的静态页面切出来,首先给 index.jsx 添加如下代码: ```jsx import React from 'react'

import s from './style.module.less'

const Login = () => { return

}

export default Login ```

为它添加一个路由配置,打开 router/index.js 添加如下: jsx import Login from '@/pages/Login' ... { path: "/login", component: Login }

重启项目,如下所示代表登录注册页面创建成功了:

image.png

接下来为 Login/index.jsx 添加静态页面代码:

```jsx import React from 'react' import { Cell, Input, Button, Checkbox } from 'zarm' import CustomIcon from '@/components/CustomIcon'

import s from './style.module.less'

const Login = () => { return

注册
}> }>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值