实战指南:制作响应式登录页

本文是《React管理平台》第九节

通过本文我们将学会登录页的制作过程

布局

根据设计图制作登录页面,我们采用了Ant Design组件库进行布局,并加以CSS样式定制,使得布局对不同屏幕尺寸友好。

UI设计图

实战指南:制作响应式登录页

HTML布局核心代码

下面是Login.tsx文件的HTML部分代码,使用了Ant Design的Form, Input, 和Button组件:

<div className={styles.loginBackground}>
  <div className={styles.login}>
    <div className={styles.title}>用户登录</div>
    <div className={styles.subTitle}>User Login</div>
    <Form name='basic' className={styles.loginForm} initialValues={{ remember: true }} onFinish={onFinish}>
      <Form.Item name='username' rules={[{ required: true, message: '请输入用户名!' }]}>
        <Input placeholder='用户名' size='large' />
      </Form.Item>

      <Form.Item name='password' rules={[{ required: true, message: '请输入密码!' }]}>
        <Input.Password placeholder='密码' autoComplete='new-password' size='large' />
      </Form.Item>

      <Form.Item>
        <Button
          className={styles.loginSubmit}
          size='large'
          type='primary'
          block
          htmlType='submit'
          loading={loading}
        >
          登录
        </Button>
      </Form.Item>
    </Form>
  </div>
</div>

这里需要注意,我们在Input.Password组件上使用了autoComplete='new-password'即可禁用浏览器的账号密码填充

如果只给密码加上autoComplete='new-password',编辑器会出现警告

实战指南:制作响应式登录页

所以<Input placeholder='用户名' autoComplete='new-password' size='large' />也需要加上autoComplete

CSS

CSS样式适配不同屏幕尺寸的响应式设计,代码如下:

.loginBackground{
  height: 100vh;
  background: url("@/assets/images/login/loginBackground.png") center no-repeat;
  display: flex;
  justify-content: center;
  align-items: center;
}
.login{
  position: absolute;
  margin-left: 140px;
  left: 50%;
  top: 0;
  bottom:0;
  width: 450px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.title{
  font-size: 34px;
  color: #4e4e4e;
  letter-spacing: 4px;
}

.subTitle{
  font-size: 18px;
  color: #4e4e4e;
}
.loginForm{
  margin-top: 50px;
}
.loginSubmit{
  margin-top: 10px;
}

:global(.ant-input-outlined){
  background: #f6f9fe;
  border:1px solid #f6f9fe;
  height: 52px;
  border-radius: 26px;
  padding: 0 30px;
}
:global(.ant-input::placeholder){
  color:#1a76e1;

}
:global(.ant-btn-primary){
  background:#1a76e1;
  height: 52px;
  font-size: 24px;
  border-radius: 26px;
}

/* 媒体查询样式 */
@media (max-width: 1536px) and (max-height:900px) {
  .loginBackground {
    background-size: 1536px 900px;
  }

  .login {
    margin-left: 80px;
    width: 400px;
  }

}
@media (max-width: 1024px) {
  .loginBackground {
    background: #e7eeff;
  }

  .login {
    margin-left: 0;
    position: static;
    width: 80vw;
  }

  .title {
    font-size: 30px;
    text-align: center;
  }

  .subTitle {
    font-size: 16px;
    text-align: center;
  }

  :global(.ant-input-outlined) {
    background: #f8f9fe;
    height: 52px;
    border-radius: 26px;
    padding: 0 30px;
  }

  :global(.ant-input::placeholder) {
    color: #a7aaaf;
  }

  :global(.ant-btn-primary) {
    background: #4785e8;
    height: 52px;
    font-size: 20px;
    border-radius: 26px;
  }
}

在样式部分,我们使用了媒体查询以适配不同尺寸的设备,使用:global覆盖Ant Design的样式

在浏览器中的效果:

最终的登录页面在浏览器中的效果能够随屏幕大小变化而自适应,保持美观和功能性。以下是一个示例动画,展现了页面的响应式设计:

实战指南:制作响应式登录页

逻辑

loading状态

在我们的Login.tsx文件中,通过useState来控制loading状态。它在开始时被设置为false

const [loading, setLoading] = useState(false)

每当onFinish函数被调用时,我们将loading设置为true

const onFinish = async () => {
  setLoading(true)
}

在浏览器中的效果:

实战指南:制作响应式登录页

登录接口

我们在src/types/api/system目录中新增login.ts文件,该文件是登录接口的类型声明文件,内容为:

export interface LoginParams {
  username: string
  password: string
}

export interface LoginResult {
  token: string
}

启动我们之前章节中创建的json-server服务来模拟mock数据

实战指南:制作响应式登录页

登录请求接口位于src/api/system目录中的login.ts文件中。

// 登录参数与返回结果定义
export interface LoginParams { username: string; password: string; }
export interface LoginResult { token: string; }

// 登录请求与服务定义
export function postLogin(params: LoginParams) {
  return request.post<LoginResult>('/system/login', params, { isShowLoading: false, isShowError: true })
}

上述代码中,由于登录页增加了loading效果,所以全局的loading效果我们设置为false,即{ isShowLoading: false }

onFinish函数中,我们首先将loading状态设置为true,然后通过postLogin函数向后台发送请求。如果请求成功,我们将loading状态设置为false并显示成功的提示信息,最后我们将路由重定向到/welcome。一旦请求失败,我们只需要简单地把loading状态重置为false即可:

const onFinish = async (values: LoginParams) => {
  try {
    setLoading(true)
    await postLogin(values)
    setLoading(false)

    message.success('登录成功')

    router.navigate('/welcome', { replace: true }).then(() => {})
  } catch (error) {
    setLoading(false)
  }
}

我们尝试输入错误的用户名和密码,看浏览器效果:

实战指南:制作响应式登录页

现在我们尝试输入正确的用户名和密码,看浏览器效果:

实战指南:制作响应式登录页

Token存储及更新

一旦用户成功登录,我们需要保存返回的token。我们将其存储在localStorage中并在zustand的token状态中进行更新。

先导入之前章节中封装的localStorage:import storage from '@/utils/localStorage.ts'

在接口请求下边新增存储token:

const response = await postLogin(values)
storage.set('token', response.data.token) // <-这里

之后我们需要更新zustand的token

先导入

import { useUserStore } from '@/store'

调用useUserStore

const updateToken = useUserStore(state => state.updateToken)

之后在接口请求下边调用:

const response = await postLogin(values)
storage.set('token', response.data.token)
updateToken(response.data.token) // <-这里

让我在浏览器中测试:

实战指南:制作响应式登录页

完整代码

github.com/HandsomeWol…

原文链接:https://juejin.cn/post/7351301965030604834 作者:辰火流光

(0)
上一篇 2024年3月28日 下午4:11
下一篇 2024年3月28日 下午4:21

相关推荐

发表回复

登录后才能评论