登录页面的逻辑我们直接做到同一个页面中,通过一个 type 参数作为判断条件,判断当前状态是登录页面或是注册页面。

    1. ...
    2. import cx from 'classnames'
    3. ...
    4. const Login = () => {
    5. ...
    6. const [type, setType] = useState('login'); // 登录注册类型
    7. return <div className={s.auth}>
    8. ...
    9. <div className={s.tab}>
    10. <span className={cx({ [s.avtive]: type == 'login' })} onClick={() => setType('login')}>登录</span>
    11. <span className={cx({ [s.avtive]: type == 'register' })} onClick={() => setType('register')}>注册</span>
    12. </div>
    13. </div>
    14. <div className={s.form}>
    15. ...
    16. {
    17. type == 'register' ? <Cell icon={<CustomIcon type="mima" />}>
    18. <Input
    19. clearable
    20. type="text"
    21. placeholder="请输入验证码"
    22. onChange={(value) => setVerify(value)}
    23. />
    24. <Captcha ref={captchaRef} charNum={4} onChange={handleChange} />
    25. </Cell> : null
    26. }
    27. </div>
    28. <div className={s.operation}>
    29. {
    30. type == 'register' ? <div className={s.agree}>
    31. <Checkbox />
    32. <label className="text-light">阅读并同意<a>《掘掘手札条款》</a></label>
    33. </div> : null
    34. }
    35. <Button onClick={onSubmit} block theme="primary">{type == 'login' ? '登录' : '注册'}</Button>
    36. </div>
    37. }

    注意,如果引入了新的工具包,请自行安装,如上述代码就需要安装 classnames。可以通过 npm i classnames -S 指令

    此时点击触发的 onSubmit 事件也很关键,同样需要通过 type 判断是登录还是注册,修改代码如下:

    1. const onSubmit = async () => {
    2. if (!username) {
    3. Toast.show('请输入账号')
    4. return
    5. }
    6. if (!password) {
    7. Toast.show('请输入密码')
    8. return
    9. }
    10. try {
    11. // 判断是否是登录状态
    12. if (type == 'login') {
    13. // 执行登录接口,获取 token
    14. const { data } = await post('/api/user/login', {
    15. username,
    16. password
    17. });
    18. // 将 token 写入 localStorage
    19. localStorage.setItem('token', data.token);
    20. } else {
    21. if (!verify) {
    22. Toast.show('请输入验证码')
    23. return
    24. };
    25. if (verify != captcha) {
    26. Toast.show('验证码错误')
    27. return
    28. };
    29. const { data } = await post('/api/user/register', {
    30. username,
    31. password
    32. });
    33. Toast.show('注册成功');
    34. // 注册成功,自动将 tab 切换到 login 状态
    35. setType('login');
    36. }
    37. } catch (error) {
    38. Toast.show('系统错误');
    39. }
    40. };

    由于登录注册的账号和密码是同一参数,我们这边就直接复用了逻辑,并通过 type 判断调用哪一个接口。
    重启项目,验证登录接口是否成功,如果成功则会返回 token 信息.
    此时,我们本地的 localStorage 里,已经存下了 token,如下图所示:
    image.png

    到此,我们的登录注册页面算是完成了,我们拿到的 token 是有时效性的,后台设置的是 24 小时的时效,如果过期了,请求其他接口时,就会报错,从而通过逻辑判断重新回到登录页面。下一章节,我会详细分析这块内容。