bubu智聘App亮点详解(3)-JWT鉴权登录和Grid布局

209 阅读5分钟

接着续写项目亮点难点详解,今天要介绍的是JWT登录鉴权和Grid布局,同时这个项目最让我兴奋的是实现了完整的JWT登录认证流程,还有那个超现代的Grid布局页面。下面我就来详细分享我的实现过程和技术心得。

同样的,在介绍之前,我们先来看看具体效果:

2.gif

一、JWT登录认证:安全之门的设计

想象一下,用户打开App的第一道门就是登录界面。我在项目中用JWT(JSON Web Token)技术打造了这扇安全门,让用户能安全地进入自己的账号空间(这里我只对我的进行了JWT登录鉴权,大家开源对任何页面做登录鉴权)。

登录界面实现思路

  1. 用户输入用户名和密码
  2. 点击登录按钮时发送验证请求
  3. 服务器验证通过后返回加密的Token
  4. 前端保存Token并跳转到账号页面

看看我的登录页面代码实现:

// Login.jsx核心代码
const handleLogin = async (e) => {
  e.preventDefault();
  const result = await login({ username, password });
  
  if (result && result.message) {
    alert(result.message); // 显示错误提示
  }
  
  if (result && result.success) {
    navigate('/acount'); // 登录成功后跳转
  }
};

由于该项目是不存在后端的,所以我写死了两个用户,当用户提交表单,会到mock模拟的数据会进行匹配,匹配成功就会返回成功的信息,随后跳转到我的界面(也就是我们做登录鉴权的页面)

<div className={styles.loginUsername}>
  <div className={styles.loginUsernameIcon}>
    <Contact />
    <p>用户名</p>
  </div>
  <input
    type="text"
    placeholder='请输入用户名'
    value={username}
    onChange={(e) => setUsername(e.target.value)}
    required
  />
</div>

登录表单的设计也很讲究,我用了React Vant的组件库来构建UI,使其更美观,项目中Loading组件,tabbar组件以及图标都来自React Vant的组件库,在企业中的开发也是如此,70%的组件都是已经写好的

二、JWT认证的魔法原理

JWT就像一张数字身份证,由三部分组成:

  1. Header(头部):说明类型和签名算法
  2. Payload(有效载荷):包含用户信息
  3. Signature(签名):防伪标识

在我的项目中,JWT的生成和验证是这样工作的:

后端生成Token(data.js)

// 使用jsonwebtoken生成Token
const token = jwt.sign({
  user: {
    id: username === 'job_seeker1' ? '001' : '002',
    username,
  }
}, secret, {
  expiresIn: 86400, // 24小时有效期
});

前端存储Token(useUserStore.js)

// 登录成功后保存Token
localStorage.setItem('token', token);
set({
  user: userData.username,
  isLogin: true,
  isLoading: false
});

验证Token(data.js)

// 验证Token有效性
const decode = jwt.verify(token, secret);
return {
  code: 0,
  user: decode.username
};

这种设计最大的好处是无状态——服务器不需要保存会话信息,每次请求都自带认证信息,特别适合分布式系统。

三、账号中心的Grid布局艺术

登录成功后,用户就来到了账号中心页面。这里我使用了CSS Grid布局来创建响应式功能网格,效果超级炫酷!

Grid布局的核心优势

  1. 二维布局能力(行和列同时控制)
  2. 灵活的项目定位
  3. 响应式设计友好
  4. 代码简洁易维护

来看看我的实现代码:

/* Acount.module.css */
.otherFunctionList {
  display: grid;
  grid-template-columns: repeat(4, 1fr); /* 4列 */
  gap: 15px; /* 网格间距 */
}

.otherFunctionItem {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 15px 10px;
  border-radius: 8px;
  transition: all 0.3s ease; /* 平滑过渡效果 */
}

.otherFunctionItem:hover {
  background-color: #f5f5f5;
  transform: translateY(-2px); /* 悬停上浮效果 */
}

在JSX中动态渲染功能网格:

<div className={styles.otherFunctionList}>
  {otherFunctionList.map((item, index) => (
    <div key={index} className={styles.otherFunctionItem}>
      <div className={styles.otherFunctionIcon}>
        {item.icon}
      </div>
      <div className={styles.otherFunctionText}>
        {item.title}
      </div>
    </div>
  ))}
</div>

image.png

这个网格布局会自动根据屏幕大小调整,在手机上会变成2列,在平板上是3列,在桌面上是4列。每个功能块都有悬停效果,给用户即时的视觉反馈。

四、状态管理:Zustand的妙用

在整个项目中,用户状态管理是个关键点。我选择了Zustand这个轻量级状态管理库,它比Redux简单,比Context更强大。

用户状态存储(useUserStore.js)

export const useUserStore = create((set) => ({
  user: null, // 当前用户
  isLogin: false, // 是否登录
  isLoading: false, // 加载状态
  
  // 登录方法
  login: async ({ username = '', password = '' }) => {
    set({ isLoading: true }); // 开始加载
    
    const data = await doLogin({ username, password });
    
    if (data.code === 0) {
      // 登录成功处理
      localStorage.setItem('token', token);
      set({
        user: userData.username,
        isLogin: true,
        isLoading: false
      });
      return { success: true };
    } else {
      // 登录失败处理
      set({
        user: null,
        isLoading: false,
        isLogin: false
      });
      return { success: false };
    }
  },
  
  // 其他方法...
}));

在组件中使用状态超级简单:

// 在组件中获取用户状态
const { user, isLogin, isLoading } = useUserStore();

五、路由与权限控制

App的路由结构设计也很讲究,我使用了React Router的嵌套路由:

// App.jsx路由配置
<Routes>
  <Route path='/' element={<MainLayout />}>
    <Route path='/' element={<Navigate to='/home' />} />
    <Route path='/home' element={<Home />} />
    <Route path='/aiConversation' element={<AiConversation />} />
    <Route path='/acount' element={
      <RequireAuth>
        <Acount /> {/* 需要登录的页面 */}
      </RequireAuth>
    } />
  </Route>
  <Route path='/' element={<Blanklayout />}>
    <Route path='/login' element={<Login />} />
    {/* 其他公共页面... */}
  </Route>
</Routes>

特别注意RequireAuth组件,它实现了页面级的权限控制:

// 检查登录状态的高阶组件
const RequireAuth = ({ children }) => {
  const { isLogin } = useUserStore();
  
  if (!isLogin) {
    return <Navigate to="/login" />;
  }
  
  return children;
};

六、用户体验的细节打磨

在整个项目中,我特别注意用户体验的细节:

1. 登录页的贴心设计

{/* 测试账号快速登录按钮 */}
<Button
  onClick={() => {
    setUsername('job_seeker1')
    setPassword('123456')
  }}
>
  求职者1测试登录
</Button>

{/* 密码可见性切换 */}
{password && <Close fontSize={15} onClick={() => setPassword('')} />}

2. 加载状态反馈

{isLoading && <Loading type='ball' className='fixed-loading' />}

3. 页面标题管理

// 自定义Hook动态设置页面标题
useTitle('bubu智聘账号中心');

4. 平滑的过渡动画

.otherFunctionItem {
  transition: all 0.3s ease;
}

总结与收获

通过这个项目,我深刻理解了:

  1. JWT认证的完整流程和实现细节
  2. Grid布局的强大和灵活
  3. Zustand状态管理的简洁高效
  4. Mock数据在前端开发中的重要性
  5. 用户体验设计的诸多细节

最让我自豪的是登录流程和账号中心的实现。当看到用户从登录页无缝跳转到漂亮的账号中心,所有功能都完美运行时,那种成就感太棒了!

技术要点回顾

  • JWT是认证的基石,确保安全
  • Grid布局让界面更现代
  • Zustand简化状态管理
  • Mock数据加速开发
  • 路由控制保护敏感页面