# 注册登录
# 技术点
vuex 的使用
登录信息存入 vuex
验证码输入框
找回密码流程
短信发送倒计时
# 目录结构
└─ src
└─ views
└─ account # 账号相关
├─ components
│ └─ CaptchaModal.vue # 图片验证码
├─ login.vue # 账号登录
├─ register.vue # 账号注册
└─ forget.vue # 忘记密码
提示
本项目中账号注册与找回密码,均使用短信验证码方式进行校验。
# 注册
流程:输入手机号->点击发送验证码->输入图形验证码->后端校验成功->后端发送验证码->手机接收验证码并填入->注册->手机验证码校验成功->后端返回 token
->登录成功
# 倒计时
methods: {
// 倒计时,计时器时间需要写入本地存储,防止用户刷新后重新计时
doLoop() {
this.second--;
localStorage.setItem("second", this.second);
if (this.second > 0) {
this.codeText = this.second + " s";
} else {
clearInterval(this.clock); //清除js定时器
this.sendWaiting = false;
this.codeText = "获取验证码";
this.second = 120; //重置时间
}
}
}
# 登录
登录流程较为简单,登录相关方法定义在了全局状态管理 vuex
中,登录成功后的信息也会存在全局中。
需要注意的是,在 http/index.js
文件中,接口返回拦截器 axios.interceptors.response
中,会对需要校验权限的接口进行拦截处理,处理代码如下:
// 用户未登录或者 token 身份失效
if (status === 401) {
// 清空 vuex 中的用户信息
store.commit("user/SET_USER", null);
store.commit("user/SET_TOKEN", "");
localStorage.removeItem("user");
localStorage.removeItem("token");
// 除一下几个路由页面在用户身份失效后不进行跳转,其它页面均会跳转到登录页面,
// 且会携带上当前页面路由地址,以便登录成功后重定向到之前页面。
if (!['Login', 'Profile', 'Register', 'NotFound', 'Forget'].includes(router.currentRoute.name)) {
router.push({
path: '/login',
query: { redirect: router.currentRoute.fullPath }
})
}
return error.response.data
}
methods: {
// 用户登录
doLogin() {
// ... 以上省略账号密码等前端校验
try {
// 执行 vuex 中的用户登录方法
const loginRes = await this.$store.dispatch("user/login", this.form);
if (loginRes.code !== 200) {
this.loading = false;
this.$toast(loginRes.message);
return;
}
// 执行 vuex 中的获取用户信息方法
const userRes = await this.$store.dispatch("user/getInfo");
this.loading = false;
// 登录成功
if (userRes.code === 200) {
this.$toast("登录成功");
sessionStorage.setItem("account", this.form.account);
// 如果是从其它需要登录权限的页面进入到登录页面,
// 登录成功后则重定向到该页面,否则跳转到首页
this.$router.replace(this.$route.query.redirect || "/home");
}
} catch (e) {
this.loading = false;
}
}
}
# 找回密码
流程:输入手机号->校验存在->获取手机验证码->输入图形验证码->后端校验成功->发送手机验证码->输入手机验证码->后端校验成功->输入新密码->完成->重新登录
# 图片验证码
如下图所示,在点击验证码时,会出现一个弹窗,上部分的图形验证码是由后端生成的base64图片,通过接口获取;下半部分为4个短横线作为输入框内容区。
# 输入框实现方式
四个短横线并非输入框,只是四个 div
元素做出的展示样式,真正的输入框为覆盖在这四个短横线上的一个绝对定位的透明背景 input
输入框。通过 watch
监听输入框内容变化,将输入框内容分别展示在短横线上。
# 核心代码
图形验证码输入框
<div class="code-input-main">
<!-- 输入验证码展示区 -->
<div
class="code-input-main-item"
v-for="(item, index) in codeList"
:key="index"
>
{{ code[index] || "" }}
</div>
<!-- 验证码实际输入框 -->
<input
ref="codeInput"
class="code-input"
v-model.trim="code"
:maxlength="codeLength"
@input="inputChange"
type="tel"
/>
</div>
输入框内容监听与拆分
watch: {
code() {
if (this.code.length > this.codeLength) {
this.code = this.code.substring(0, this.codeLength);
}
}
}