登录页面的逻辑我们直接做到同一个页面中,通过一个 type 参数作为判断条件,判断当前状态是登录页面或是注册页面。
...import cx from 'classnames'...const Login = () => {...const [type, setType] = useState('login'); // 登录注册类型return <div className={s.auth}>...<div className={s.tab}><span className={cx({ [s.avtive]: type == 'login' })} onClick={() => setType('login')}>登录</span><span className={cx({ [s.avtive]: type == 'register' })} onClick={() => setType('register')}>注册</span></div></div><div className={s.form}>...{type == 'register' ? <Cell icon={<CustomIcon type="mima" />}><Inputclearabletype="text"placeholder="请输入验证码"onChange={(value) => setVerify(value)}/><Captcha ref={captchaRef} charNum={4} onChange={handleChange} /></Cell> : null}</div><div className={s.operation}>{type == 'register' ? <div className={s.agree}><Checkbox /><label className="text-light">阅读并同意<a>《掘掘手札条款》</a></label></div> : null}<Button onClick={onSubmit} block theme="primary">{type == 'login' ? '登录' : '注册'}</Button></div>}
注意,如果引入了新的工具包,请自行安装,如上述代码就需要安装 classnames。可以通过 npm i classnames -S 指令
此时点击触发的 onSubmit 事件也很关键,同样需要通过 type 判断是登录还是注册,修改代码如下:
const onSubmit = async () => {if (!username) {Toast.show('请输入账号')return}if (!password) {Toast.show('请输入密码')return}try {// 判断是否是登录状态if (type == 'login') {// 执行登录接口,获取 tokenconst { data } = await post('/api/user/login', {username,password});// 将 token 写入 localStoragelocalStorage.setItem('token', data.token);} else {if (!verify) {Toast.show('请输入验证码')return};if (verify != captcha) {Toast.show('验证码错误')return};const { data } = await post('/api/user/register', {username,password});Toast.show('注册成功');// 注册成功,自动将 tab 切换到 login 状态setType('login');}} catch (error) {Toast.show('系统错误');}};
由于登录注册的账号和密码是同一参数,我们这边就直接复用了逻辑,并通过 type 判断调用哪一个接口。
重启项目,验证登录接口是否成功,如果成功则会返回 token 信息.
此时,我们本地的 localStorage 里,已经存下了 token,如下图所示:
到此,我们的登录注册页面算是完成了,我们拿到的 token 是有时效性的,后台设置的是 24 小时的时效,如果过期了,请求其他接口时,就会报错,从而通过逻辑判断重新回到登录页面。下一章节,我会详细分析这块内容。
