react+zarm实现底部导航栏的示例代码

目录
  • 需要实现的效果
  • 实现过程
    • 1.使用 prop-types 库进行类型检查
    • 2.使用 useNavigate
    • 3.编写标签栏组件
    • 4.使用标签栏组件
    • 5.添加对应的页面路由
    • 6.效果
  • 参考资料

需要实现的效果

需要实现下面栏目固定,并且点击时切换到不同页面路由

实现过程

1.使用 prop-types 库进行类型检查

注意:自 React v15.5 起,React.PropTypes 已移入另一个包中。请使用 prop-types 库 代替。

PropTypes 提供了使用不同验证器的例子:

import PropTypes from 'prop-types';

MyComponent.propTypes = {
  // 你可以将属性声明为 JS 原生类型,默认情况下
  // 这些属性都是可选的。
  optionalArray: PropTypes.array,
  optionalBool: PropTypes.bool,
  optionalFunc: PropTypes.func,
  optionalNumber: PropTypes.number,
  optionalObject: PropTypes.object,
  optionalString: PropTypes.string,
  optionalSymbol: PropTypes.symbol,

  // 任何可被渲染的元素(包括数字、字符串、元素或数组)
  // (或 Fragment) 也包含这些类型。
  optionalNode: PropTypes.node,

  // 一个 React 元素。
  optionalElement: PropTypes.element,

  // 一个 React 元素类型(即,MyComponent)。
  optionalElementType: PropTypes.elementType,

  // 你也可以声明 prop 为类的实例,这里使用
  // JS 的 instanceof 操作符。
  optionalMessage: PropTypes.instanceOf(Message),

  // 你可以让你的 prop 只能是特定的值,指定它为
  // 枚举类型。
  optionalEnum: PropTypes.oneOf(['News', 'Photos']),

  // 一个对象可以是几种类型中的任意一个类型
  optionalUnion: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.instanceOf(Message)
  ]),

  // 可以指定一个数组由某一类型的元素组成
  optionalArrayOf: PropTypes.arrayOf(PropTypes.number),

  // 可以指定一个对象由某一类型的值组成
  optionalObjectOf: PropTypes.objectOf(PropTypes.number),

  // 可以指定一个对象由特定的类型值组成
  optionalObjectWithShape: PropTypes.shape({
    color: PropTypes.string,
    fontSize: PropTypes.number
  }),

  // An object with warnings on extra properties
  optionalObjectWithStrictShape: PropTypes.exact({
    name: PropTypes.string,
    quantity: PropTypes.number
  }),

  // 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保
  // 这个 prop 没有被提供时,会打印警告信息。
  requiredFunc: PropTypes.func.isRequired,

  // 任意类型的必需数据
  requiredAny: PropTypes.any.isRequired,

  // 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。
  // 请不要使用 `console.warn` 或抛出异常,因为这在 `oneOfType` 中不会起作用。
  customProp: function(props, propName, componentName) {
    if (!/matchme/.test(props[propName])) {
      return new Error(
        'Invalid prop `' + propName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }
  },

  // 你也可以提供一个自定义的 `arrayOf` 或 `objectOf` 验证器。
  // 它应该在验证失败时返回一个 Error 对象。
  // 验证器将验证数组或对象中的每个值。验证器的前两个参数
  // 第一个是数组或对象本身
  // 第二个是他们当前的键。
  customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
    if (!/matchme/.test(propValue[key])) {
      return new Error(
        'Invalid prop `' + propFullName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }
  })
};

安装依赖:

npm i prop-types -S

2.使用 useNavigate

v6 用 useNavigate 替代了 useHistory,其返回了一个 navigate (点击查看用法) 的方法,实现比较简单:

  • NavigationContext 拿到 navigator,也就是 history 实例。
  • 然后根据 to、matches 的每项 pathnameBase 以及当前 URL pathname 生成最终的路径 path({pathname, search, hash})
  • 根据是否指定 replace 来判断是调用 replace 还是 push 方法
// v5
import { useHistory } from 'react-router-dom';

function MyButton() {
  let history = useHistory();
  function handleClick() {
    history.push('/home');
  };
  return <button onClick={handleClick}>Submit</button>;
};

现在,history.push() 将替换为 navigation()

// v6
import { useNavigate } from 'react-router-dom';

function MyButton() {
  let navigate = useNavigate();
  function handleClick() {
    navigate('/home');
  };
  return <button onClick={handleClick}>Submit</button>;
};

3.编写标签栏组件

新建 components/NavBar/index.jsx 文件,用于编写底部导航栏,代码如下所示:

import React, { useState } from 'react';
import PropTypes from 'prop-types'
import { TabBar } from 'zarm';
import { useNavigate, useLocation } from 'react-router-dom';
import CustomIcon from '../CustomIcon'
import s from './style.module.less';

const NavBar = ({ showNav }) => {
  const location = useLocation() // 拿到 location 实例
  const { pathname } = location // 获取当前路径
  console.log('navbar pathname', pathname)
  const [activeKey, setActiveKey] = useState(pathname);
  const navigate = useNavigate()

  const changeTab = (path) => {
    setActiveKey(path)
    navigate(path)
  }

  return (
    <TabBar visible={showNav} className={s.tab} activeKey={activeKey} onChange={changeTab}>
      <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="user" />}
      />
    </TabBar>
  );
};

NavBar.propTypes = {
  showNav: PropTypes.bool
}

export default NavBar;

新建 components/NavBar/style.module.less 文件,用于编写底部导航栏样式,代码如下所示:

.tab {
    border-top: 1px solid #e9e9e9;
}

4.使用标签栏组件

打开 App.jsx,添加如下代码:

import React, { useState, useEffect } from 'react'
import NavBar from '@/components/NavBar';
import { Routes, Route, useLocation, BrowserRouter } from 'react-router-dom'

import { ConfigProvider } from 'zarm';

import routes from '../src/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 <BrowserRouter>
    <ConfigProvider primaryColor={'#007fff'}>
      <Routes>
        {
          routes.map(route => <Route key={route.path} path={route.path} element={<route.component />}></Route>)
        }
      </Routes>
    </ConfigProvider>
    <NavBar showNav={showNav} />
  </BrowserRouter>
}

export default App

我们发现报错了:Uncaught Error: You cannot render a <Router> inside another <Router>. You should never have more than one in your app.

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

App.jsx 里面

import React, { useState, useEffect } from 'react'
import NavBar from '@/components/NavBar';
import { Routes, Route, useLocation } from 'react-router-dom'

import { ConfigProvider } from 'zarm';

import routes from '../src/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 <>
    <ConfigProvider primaryColor={'#007fff'}>
      <Routes>
        {
          routes.map(route => <Route key={route.path} path={route.path} element={<route.component />}></Route>)
        }
      </Routes>
    </ConfigProvider>
    <NavBar showNav={showNav} />
  </>
}

export default App

main.jsx

import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router-dom'

import 'lib-flexible/flexible'

import './index.css'
import App from './App'

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
)

5.添加对应的页面路由

在 container 文件夹里添加下面三个模块的页面

// 账单
import React from 'react'

const Home = () => {
  return <div>账单</div>
}

export default Home
// 统计
import React from 'react'

const Data = () => {
  return <div>统计</div>
}

export default Data
// 个人中心
import React from 'react'

const User = () => {
  return <div>个人中心</div>
}

export default User

然后在 router/index.js 添加路由:

import Login from '@/container/Login'
import Home from '@/container/Home'
import Data from '@/container/Data'
import User from '@/container/User'

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

export default routes

6.效果

我们可以切换到统计,然后刷新,发现也是没有问题。

参考资料

到此这篇关于react+zarm实现底部导航栏的示例代码的文章就介绍到这了,更多相关react 底部导航栏内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • react实现导航栏二级联动

    本文实例为大家分享了react实现导航栏二级联动的具体代码,供大家参考,具体内容如下 效果图 js代码 import { Component } from "react"; import './scroll.less'   class Scroll extends Component {     constructor(...args) {         super(...args)         this.state = {             list: [        

  • Android开发之React Navigation 导航栏样式调整+底部角标消息提示

    五一佳节匆匆而过,有人选择在外面看人山人海,有人选择宅在家中度过五一,也有人依然坚守在第一线,致敬! 这是坚持学习react-native的第二篇文章,可能会迟到,但是绝不会缺席,这篇要涉及到的是react-navigation,也是rn社区主推的一个导航库. 网上关于react-navigation的基本使用也是一抓一大把,这里对于它的使用不做过多介绍,主要记录使用过程中的其他问题. 因为android 和iOS 手机的不同,导航栏的显示也不太一样,而这篇文章会尽量的配置属性,让两端的导航栏样

  • react+zarm实现底部导航栏的示例代码

    目录 需要实现的效果 实现过程 1.使用 prop-types 库进行类型检查 2.使用 useNavigate 3.编写标签栏组件 4.使用标签栏组件 5.添加对应的页面路由 6.效果 参考资料 需要实现的效果 需要实现下面栏目固定,并且点击时切换到不同页面路由 实现过程 1.使用 prop-types 库进行类型检查 注意:自 React v15.5 起,React.PropTypes 已移入另一个包中.请使用 prop-types 库 代替. PropTypes 提供了使用不同验证器的例子

  • element-ui 实现响应式导航栏的示例代码

    开始之前 按照计划,前端使用Vue.js+Element UI,但在设计导航栏时,发现element没有提供传统意义上的页面顶部导航栏组件,只有一个可以用在很多需要选择tab场景的导航菜单,便决定在其基础上改造,由于我认为实现移动端良好的体验是必须的,所以便萌生了给其增加响应式功能的想法. 需求分析与拆解 假设我们的导航栏有logo和四个el-menu-item. 给window绑定监听事件,当宽度小于a时,四个链接全部放入右侧el-submenu的子菜单: 当宽度大于a时,右侧el-subme

  • iOS实现导航栏透明示例代码

    在最近一个项目中碰到这样一个场景,在被push进来的一个页面设置导航栏透明,且要求控制对tableview组的头视图进行悬停显示,nav随着tableview偏移量改变透明度,当然这样的需求确实不是什么难事,但是如果当前页面继续push一个不需要此类效果的页面,当在返回当前页面的时候就会出现一个坑,nav的展示很突兀,下面是直接上解决方法...ps:假设A页面为需要设置透明,B页面被Apush且不需要设置透明 首先在需要设置导航栏透明的页面的viewDidload中写上 self.title =

  • flutter BottomAppBar实现不规则底部导航栏

    本文实例为大家分享了flutter实现不规则底部导航栏的具体代码,供大家参考,具体内容如下 实现底部导航栏并点击切换页面可简述为有三种方式 TabBar + TabBarView BottomNavigationBar + BottomNavigationBarItem 自定义 BottomAppBar 在这里 使用 BottomAppBar 来实现 /** * 有状态StatefulWidget * 继承于 StatefulWidget,通过 State 的 build 方法去构建控件 */

  • Flutter实现底部导航栏

    本文实例为大家分享了Flutter实现底部导航栏的具体代码,供大家参考,具体内容如下 效果 实现 先将自动生成的main.dart里面的代码删除, import 'package:flutter/material.dart'; import 'package:flutter_guohe/pages/main.dart'; void main() { runApp(new Guohe()); } 创建app.dart作为首页的页面文件 class Guohe extends StatefulWid

  • Flutter底部导航栏的实现方式

    本文实例为大家分享了Flutter底部导航栏的实现代码,供大家参考,具体内容如下 老规格,先看图: 程序主结构如下: 1.在程序主入口文件main.dart添加如下代码 import 'package:flutter/material.dart'; import 'bottom_navigation.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build

  • Android使用BottomNavigationBar实现底部导航栏

    本文实例为大家分享了Android实现底部导航栏的具体代码,供大家参考,具体内容如下 展示 MODE_FIXED+BACKGROUND_STYLE_STATIC效果 DE_FIXED+BACKGROUND_STYLE_RIPPLE效果 MODE_SHIFTING+BACKGROUND_STYLE_STATIC效果 MODE_SHIFTING+BACKGROUND_STYLE_RIPPLE效果 1在Gradle中添加 compile 'com.ashokvarma.android:bottom-n

  • android实现简单底部导航栏

    本文实例为大家分享了android实现底部导航栏的具体代码,供大家参考,具体内容如下 常见的底部导航栏 动态效果 实现步骤 1.底部导航栏样式 我们应该在项目的res文件夹下新建一个menu文件夹,用来装menu布局文件 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"&g

  • Flutter自定义底部导航栏的方法

    本文实例为大家分享了Flutter自定义底部导航栏的具体代码,供大家参考,具体内容如下 文件结构: main.dart import 'package:flutter/material.dart'; import 'pages/tabs.dart';   void main() => runApp(new MyApp());   class MyApp extends StatelessWidget {   @override   Widget build(BuildContext contex

  • Android开发快速实现底部导航栏示例

    目录 Tint 着色器 依赖(AndroidX) 布局 编写渲染颜色选择器-tint_selector_menu_color menu 文件中 icon-nav_bottom_menu BottomNavigationView的点击事件 配合ViewPager实现Tab栏 对应的适配器 Tint 着色器 优点:去除“无用”图片,节省空间 配合BottomNavigationView,实现一个快速,简洁的Tab栏 传统做法:Tab 切换,字体变色.图片变色.至少给我提供八张图,四张默认,四张选中,

随机推荐