# 注册登录

# 技术点

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个短横线作为输入框内容区。
image.png

# 输入框实现方式

四个短横线并非输入框,只是四个 div 元素做出的展示样式,真正的输入框为覆盖在这四个短横线上的一个绝对定位的透明背景 input 输入框。通过 watch 监听输入框内容变化,将输入框内容分别展示在短横线上。
image.png

# 核心代码

图形验证码输入框

<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);
		}
	}
}
上次更新: 6/27/2022, 5:48:02 PM
示例展示,因PC端无touch事件,请在手机上进行浏览