使用 React 和 Tailwind 创建响应式导航栏
让我们开始编程吧
概述
即使现在已经是2021年底,而且我们已经尽一切努力确保应用程序能够从移动设备到桌面设备无缝响应,但这些应用程序仍然带有明显的网页风格。
我的意思是,即使我们知道应该采用哪些类型的组件或采取哪些行为才能更好地让我们的应用程序在移动平台上得到应用,我们仍然继续做同样的事情。
以顶部导航栏为例,一旦屏幕分辨率达到移动设备水平,我们就会看到常见的汉堡菜单,然后为了与每个导航元素交互,我们会使用下拉菜单或全屏菜单。但实际上,在大多数情况下,一个标签栏就足够了。
我推荐阅读的资料之一是Material Design文档,在我看来,它是通过实例获取知识的最佳途径。
今天的例子
我今天文章的主题是创建两个导航组件,其中一个是页面顶部的导航栏,当屏幕分辨率高于平板电脑时就会显示。但如果屏幕分辨率低于桌面电脑,则会显示标签栏。
为了让大家更好地理解我的意思,我希望读完这篇文章后,你们能得出以下结论:
如您所见,在这两个组件中,我们都通过给元素添加边框和非常微妙的渐变来确保用户能够导航到当前页面。
让我们开始编程吧
今天我们将使用的框架是 Tailwind CSS,同时我们还将使用其他工具,例如 classnames 和 react-icons。
npm install classnames react-icons
之后,我们将创建一个文件,文件名就是我们将要使用的导航元素的名称。
// @src/data/navigation.js
export default ["Home", "Discover", "Store", "Inbox", "Profile"];
接下来,我们来创建钩子(只是为了将逻辑从选定的导航元素中抽象出来)。其中首页将是“Home”,然后我们将创建一个角色负责更改当前路由。
// @src/hooks/useNavigation.js
import { useState, useCallback } from "react";
const useNavigation = () => {
const [route, setRoute] = useState("Home");
const selectAction = useCallback(
(option) => {
if (route === option) return;
setRoute(option);
},
[route]
);
return { currentRoute: route, setCurrentRoute: selectAction };
};
export default useNavigation;
现在我们可以开始制作组件了。首先来制作导航栏。以下是导航栏组件的样式:
/* @src/components/Navbar/Navbar.module.css */
.navbar {
@apply hidden md:flex flex-row items-center justify-between px-8 h-18 rounded-b-3xl bg-white;
}
.logo {
@apply text-5xl text-gray-800 -mb-1;
}
.navItems {
@apply flex flex-row self-end h-12;
}
.navItem {
@apply w-22 text-gray-400 hover:text-gray-700 cursor-pointer font-medium tracking-wide text-sm flex items-start justify-center;
}
.selectedNavItem {
@apply text-gray-700 border-b-3 border-gray-700 bg-gradient-to-b from-white to-gray-100;
}
.actions {
@apply bg-white hover:bg-gray-50 border-2 border-gray-900 text-sm text-gray-900 py-3 px-5 rounded-lg font-medium tracking-wide leading-none;
}
我们的组件将接收三个 props:导航元素、当前路由以及用于定义当前路由的函数。然后,我们将映射数组元素,使导航栏中包含每个导航元素,并使用类名进行条件渲染,以便将不同的类连接起来。
// @src/components/Navbar/index.jsx
import React from "react";
import { CgMonday } from "react-icons/cg";
import classNames from "classnames";
import styles from "./Navbar.module.css";
const Navbar = ({ navigationData, currentRoute, setCurrentRoute }) => {
return (
<nav className={styles.navbar}>
<span className={styles.logo}>
<CgMonday />
</span>
<ul className={styles.navItems}>
{navigationData.map((item, index) => (
<li
className={classNames([
styles.navItem,
currentRoute === item && styles.selectedNavItem,
])}
key={index}
onClick={() => setCurrentRoute(item)}
>
{item}
</li>
))}
</ul>
<button className={styles.actions}>Logout</button>
</nav>
);
};
export default Navbar;
导航栏完成后,我们可以开始制作标签栏了。样式如下:
/* @src/components/Tabbar/Tabbar.module.css */
.tabbar {
@apply flex md:hidden flex-row items-center justify-around px-8 h-18 bg-white visible md:invisible fixed bottom-0 w-full rounded-t-3xl text-2xl;
}
.tabItem {
@apply text-gray-400 hover:text-gray-700 cursor-pointer w-18 h-full flex items-center justify-center;
}
.tabItemActive {
@apply bg-gradient-to-t from-white to-gray-100 border-t-3 border-gray-700 text-gray-700;
}
.icon {
@apply -mb-1;
}
这个组件会接收与导航栏完全相同的 props,但这次我们需要实现一个非常简单的条件渲染。在数组元素映射中,我们需要渲染路由对应的图标,因此我们将创建一个带有 switch 语句的函数,该函数将负责根据元素返回相应的图标。
// @src/components/Tabbar/index.jsx
import React, { useCallback } from "react";
import classNames from "classnames";
import { AiFillHome, AiFillCompass } from "react-icons/ai";
import { BsFillBagFill, BsFillPersonFill } from "react-icons/bs";
import { CgInbox } from "react-icons/cg";
import styles from "./Tabbar.module.css";
const Tabbar = ({ navigationData, currentRoute, setCurrentRoute }) => {
const getTabIcon = useCallback((item) => {
switch (item) {
case "Home":
return <AiFillHome />;
case "Discover":
return <AiFillCompass />;
case "Store":
return <BsFillBagFill />;
case "Inbox":
return <CgInbox />;
case "Profile":
return <BsFillPersonFill />;
}
}, []);
return (
<nav className={styles.tabbar}>
{navigationData.map((item, index) => (
<span
key={index}
className={classNames([
styles.tabItem,
currentRoute === item && styles.tabItemActive,
])}
onClick={() => setCurrentRoute(item)}
>
<span className={styles.icon}>{getTabIcon(item)}</span>
</span>
))}
</nav>
);
};
export default Tabbar;
最后,我们需要打开输入文件(在本例中为 App.jsx),并设置以下样式:
/* @src/App.module.css */
.container {
@apply bg-gray-200 h-screen;
}
.devLogo {
@apply flex items-center justify-center text-5xl text-gray-300 h-5/6;
}
现在,在我们的 App.jsx 中,我们将导入导航数据、钩子函数以及我们稍后创建的每个组件,并将指定的属性传递给每个组件。
// @src/App.jsx
import React from "react";
import { FaDev } from "react-icons/fa";
import styles from "./App.module.css";
import useNavigation from "./hooks/useNavigation";
import navigationData from "./data/navigation";
import Navbar from "./components/Navbar";
import Tabbar from "./components/Tabbar";
const App = () => {
const { currentRoute, setCurrentRoute } = useNavigation();
return (
<div className={styles.container}>
<Navbar
navigationData={navigationData}
currentRoute={currentRoute}
setCurrentRoute={setCurrentRoute}
/>
<Tabbar
navigationData={navigationData}
currentRoute={currentRoute}
setCurrentRoute={setCurrentRoute}
/>
<div className={styles.devLogo}>
<FaDev />
</div>
</div>
);
};
export default App;
结论
和往常一样,希望您觉得这篇文章有趣。如果您发现文章中有任何错误,请在评论区指出。🧑🏻💻
祝你今天过得愉快!👋
文章来源:https://dev.to/franciscomendes10866/create-a-responsive-navbar-using-react-and-tailwind-3768
