如果想看该实战系列的其他内容,请移步至 Vue.js 实战系列之实现视频类WebApp的项目开发。
项目仓库地址,欢迎 Star
引入 Vuex
什么是 Vuex?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
通俗点说:此时有一个根组件和两个子组件,如果根组件与子组件之间通信,可以通过 props 传值的方式来实现;但是如果想要让两个子组件进行通信,此时实现起来就比较复杂,在未引入 Vuex 之前,可以将子组件A的内容传给父组件,然后父组件接收到再传递给子组件B,相当于父组件作为一个中介进行传递,但是引入 Vuex 之后实现起来就比较简单啦。
Vuex 官网
使用 modules
模块化管理数据
在 src/store
文件夹下,新建 modules
文件夹,创建 sign.js
模块
const sign = {
// 命名空间
namespaced: true,
state: {
// 默认的验证码
verifyCode: '000000',
},
mutations: {
},
actions: {
},
getters: {
},
};
export default sign;
更新 src/store/index.js
将刚才创建的 sign
模块导入
import Vue from 'vue';
import Vuex from 'vuex';
import sign from './modules/sign';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
sign,
},
});
验证码登录流程实现
正常流程下,验证码是由后端为我们返回的,此时我们没有真实的后端接口,所以现在我们将后端返回的验证码值写死在 state 中,后期将通过 nodejs 来实现一个后端接口,欢迎关注。
创建验证码页面 Code.vue
<template>
<div class="sign">
<div class="sign-header">
<span class="iconfont icon-guanbi" style="font-size: 30px">span>
<span style="color: #686868"> 帮助span>
div>
<div class="sign-content">
<div class="des">
<h2>请输入验证码h2>
<p>验证码已通过短信发送至+8615998362261p>
div>
div>
<div class="sign-box">
<div class="inp">
<input
v-model="code"
@input="changeCode"
type="number"
class="inp-controll"
placeholder="请输入验证码"
/>
div>
<div class="time">
{
{ time }}
div>
div>
<div class="not-dx">
<p>收不到短信?<a>获取语言验证码a>p>
div>
<div class="code-btn">
<button
:disabled="disabled"
:class="btnBg ? 'active' : ''"
@click="getCode"
>
登录
button>
div>
div>
template>
<script>
export default {
data() {
return {
// 短信发送倒计时
time: 60,
};
},
};
script>
<style lang="less" scoped>
.sign {
padding: 30px;
background: #fff;
.sign-header {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 18px;
}
.sign-content {
padding: 20px 10px;
h2 {
margin: 0;
font-size: 22px;
font-weight: bold;
}
p {
font-size: 14px;
line-height: 20px;
color: #adadad;
}
}
.sign-box {
display: flex;
height: 50px;
margin: 0;
align-items: center;
background-color: #f9f9f9;
.inp {
height: 36px;
width: 90%;
margin-left: 10px;
.inp-controll {
caret-color: #fe2c55;
height: 36px;
background-color: #f9f9f9;
width: 90%;
font-size: 16px;
border: none;
outline: none;
}
}
.time {
text-align: right;
width: 80px;
font-size: 16px;
line-height: 80px;
margin-right: 10px;
}
}
.not-dx {
margin-top: 10px;
p {
color: #b9b9b9;
font-size: 14px;
a {
color: #3d79b4;
}
}
}
.code-btn {
button {
margin: 10px 0;
width: 100%;
padding: 15px 0;
border: none;
letter-spacing: 1px;
font-size: 17px;
color: #fff;
font-weight: 600;
background: #dbdbdb;
border-radius: 2px;
}
.active {
color: #ffffff;
background-color: #fe2c55;
}
}
}
style>
更新 src/store/modules/sign.js
import router from '../../router';
const sign = {
// 命名空间
namespaced: true,
state: {
// 默认的验证码
verifyCode: '000000',
},
mutations: {
},
actions: {
// 登录操作
sign({
state, commit, rootState }, params) {
// 登录成功之后 session 中缓存登录标识
sessionStorage.setItem('isLogin', JSON.stringify(true));
// 登录成功之后 跳转到 webApp 主页
router.replace({
path: '/' });
},
},
getters: {
},
};
export default sign;
更新 Code.vue
完成登录
引入 mapActions
,调用 sign.js
中的 sign
方法实现登录
使用 this.$store.state.
获取 state
中的值
使用 van-loading
实现加载中动画
<template>
<div class="sign">
<div class="sign-header">
<span
class="iconfont icon-fanhui"
style="font-size: 30px"
@click="goBack"
>span>
<span style="color: #686868"> 帮助span>
div>
<div class="sign-content">
<div class="des">
<h2>请输入验证码h2>
<p>验证码已通过短信发送至+86{
{ tel }}p>
div>
div>
<div class="sign-box">
<div class="inp">
<input
v-model="code"
@input="changeCode"
type="number"
class="inp-controll"
placeholder="请输入验证码"
/>
div>
<div class="time">
{
{ time }}
div>
div>
<div class="not-dx">
<p>收不到短信?<a>获取语言验证码a>p>
div>
<div class="code-btn">
<button
:disabled="disabled"
:class="btnBg ? 'active' : ''"
@click="Login"
>
<div v-if="!loading">
{
{ msg }}
div>
<div v-else class="loading">
<van-loading color="#1989fa" size="16px" />
{
{ msg }}
div>
button>
div>
div>
template>
<script>
import {
mapActions } from 'vuex';
export default {
data() {
return {
tel: '', // 电话号码
code: '', // 验证码
verifyCode: '', // state中提供的默认验证码
time: 60, // 短信发送倒计时
disabled: true,
btnBg: false,
loading: false,
msg: '登录',
};
},
created() {
this.getCode();
this.tel = this.$route.query.tel;
},
methods: {
...mapActions('sign', ['sign']),
// 监听输入验证码
changeCode(e) {
this.code = e.target.value;
if (this.code === this.verifyCode) {
this.disabled = false;
this.btnBg = true;
} else {
console.log('验证码输入错误');
}
},
// 获取验证码
getCode() {
this.verifyCode = this.$store.state.sign.verifyCode;
this.countDown();
},
// 倒计时
countDown() {
if (this.time > 0) {
this.time -= 1;
setTimeout(this.countDown, 1000);
} else {
this.time = '重新发送';
}
},
// 登录按钮点击事件
Login() {
this.loading = true;
this.msg = '登录中';
setTimeout(() => {
this.loading = false;
this.msg = '登录成功';
}, 1500);
setTimeout(() => {
this.sign({
code: this.code }); // 登录跳转操作
}, 2000);
},
// 返回上个页面
goBack() {
this.$router.go(-1);
},
},
};
script>
<style lang="less" scoped>
.sign {
...
.code-btn {
button {
.loading {
display: flex;
justify-content: center;
align-items: center;
}
}
}
}
style>
本章节需要注意的几个点:
Vuex
的使用modules
模块化管理数据SessionStorage
前端数据存储上一章节: 11. 手机号登录、密码登录、其它方式登录的实现
下一章节: 13. 自定义弹出框组件的实现
项目整体介绍:Vue.js 项目实战之实现视频播放类WebApp的项目开发(仿抖音app)
项目仓库地址,欢迎 Star。
有任何问题欢迎评论区留言讨论。