Vue项目之登录注册
1.1 注册页面的布局
需要用到Vant的Field组件
1.views下新建一个注册页面 ,完成基本布局。引入Vue和Field并使用。
2.在官方文档中搜索,查看自己需要的内容,将其直接粘贴到页面中。
3.给注册页面添加一个单独的路由,注册页面不需要底部。(注意,相关样式需要引入不同的组件,请细心查看官方文档,按需拿取内容)
4. 利用计算属性给输入框做条件判断。本案例以手机号为例。
<template>
<div class="container">
<header class="header">注册</header>
<div class="content">
<van-field
v-model="username"
placeholder="请输入手机号"
clearable
:error-message="usernamemsg"
/>
<van-field
v-model="password"
type="password"
clearable
placeholder="请输入密码"
error-message="密码格式错误"
/>
<van-field
v-model="code"
center
clearable
placeholder="请输入短信验证码"
error-message="验证码格式错误"
>
<van-button slot="button" size="small" type="primary">发送验证码</van-button>
</van-field>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import { Field, Button } from 'vant'
Vue.use(Field)
Vue.use(Button)
export default {
data () {
return {
username: '18813007814',
password: '123456',
code: ''
}
},
computed: {
usernamemsg () {
if (this.username === '') {
return ''
} else if (!/^[1][3,4,5,7,8][0-9]{9}$/.test(this.username)) {
return '手机号码格式错误'
} else {
return ''
}
}
}
}
</script>
1.2 注册业务逻辑的实现
注:在此之前,记住要先去路由页面添加一个注册页面的路由。
1.补充了密码以及验证码的计算属性判断
密码:如果为空返回空,如果不符合正则,返回格式错误,否则表示可以直接返回空
验证码:如果为空返回空,否则不为五位,返回验证码格式错误,否则成功返回空
2.验证码
- 绑定点击事件senCode
- 将提示信息{{buttonmsg}}放在按钮内容中。
- 定义函数:(定时器注意用箭头函数)每一秒钟定义一次,先提前声明时间,在计时器内让时间减减,当时间为零时,清除定时器,同时btn的内容改为发送验证码,最后return。未return时,让按钮内的内容为时间减减+后重新发送(注意:在开启定时器时,要让按钮禁止点击,在清除定时器后再让按钮可点。)
3.验证码跟接口做交互
在setCode最后定义一个getCode函数,在下方定义该函数(类似面向对象写法)。
定义getCode:
- 需要引入Toast并使用,请提示
- 在该函数中也可以去验证手机号是否正确,不正确显示相关提示信息
- 否则正确,就去axios去post请求数据,然后打印数据,去判断返回信息,跟接口文档相对应,如果为1则是用户名已经注册,0为获取验证码失败,成功在data里再定义adminCode用来存放验证码,通过res.data.code可以获取,加入该值中。
4.引入一个按钮,作为注册按钮
定义register函数
1.判断:
- 将手机号的验证再写一遍,如果不符合,则toast提示,直接return
- 验证密码,不符合同样提示并return
- 验证码验证,不符合toast提示,并return
2.当上面的判断都通过,再定义真正的注册函数
- 调接口,修改注册按钮为不可点,并修改值为注册中,在注册按钮写上:loading=“loading” loading-text=“注册中” disabled=“flag”
- this.flag=true,this.loading=true
- axios的post请求数据,第二个参数为用户手机号和密码。请求成功后先去更改按钮的状态,this.flag,this.loading都改为false。 再去判断返回值(根据接口文档定义) 2->用户名已经注册,0->注册失败,否则注册成功
5.在注册页面增加登录按钮,用来做跳转。
记住不能用声明式跳转,用编程式跳转,用replace跳转到另一个页面(返回直接回到个人中心) - <template>
-
<div class="container">
<header class="header">注册头部</header>
<div class="content">
<van-field
v-model="tel"
placeholder="请输入手机号"
:error-message="usertel"
clearable
/>
<van-field
v-model="password"
type="password"
placeholder="请输入密码"
:error-message="pass"
clearable
/>
<van-field
v-model="sms"
center
clearable
placeholder="请输入短信验证码"
:error-message="test"
>
<van-button :disabled="flag" slot="button" size="small" type="primary" @click="sendCode">{{ buttonmsg }}</van-button>
</van-field>
<van-button type="primary" :loading="loading" loading-text="注册..." size="large" :disabled="zhud" @click="register">注册</van-button>
<van-divider @click="toLogin">去登录</van-divider>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import { Field,Button,Toast,Divider } from 'vant'
import axios from 'axios'
Vue.use(Field)
Vue.use(Button)
Vue.use(Toast)
Vue.use(Divider)export default {
data () {
return {
tel:'',
password:'',
sms:'',
buttonmsg:'点击发送验证码',
flag:false,
adminCode:'',
zhud:false,
loading:false
}
},
computed: {
usertel () {
if (this.tel === ""){
return ''
}else if(!/^[1][3,4,5,7,8][0-9]{9}$/.test(this.tel)){
return '手机号格式错误'
}else {
return ''
}
},
pass () {
if (this.password === ""){
return ''
}else if(this.password.length<6){
return '密码不可小于6位'
}else {
return ''
}
},
test () {
if (this.sms === ""){
return ''
}else if(this.sms.length !== 5){
return '验证码格式错误'
}else {
return ''
}
}
},
methods: {
toLogin () {
this.$router.replace('/login')
},
sendCode () {
let time = 4
let timer
timer = setInterval(()=>{
time --
if(time === 0){
clearInterval(timer)
this.flag=false
this.buttonmsg = '点击发送验证码'
return
}
this.flag = true
this.buttonmsg = time + '秒后重新发送'
},1000)
this.getCode()
},
getCode () {
if(!/^[1][3,4,5,7,8][0-9]{9}$/.test(this.tel) || this.tel===""){
Toast('手机号码输入有误')
}else{
axios.get('https://www.daxunxun.com/users/sendCode?tel='+this.tel).then(res=>{
if(res.data === 1){
Toast('用户名已注册,请更改')
}else if(res.data === 0){
Toast('获取验证码失败')
}else{
this.adminCode = res.data.code
console.log(this.adminCode)
}
})
}
},
register () {
if (this.tel === '' || this.usertel === '手机号码格式错误') {
Toast('手机号码输入有误')
return
}
if (this.password === '' || this.pass === '密码格式错误,最少为6位') {
Toast('密码输入有误')
return
}
if (this.sms === '' || this.sms !== this.adminCode) {
Toast('验证码输入有误')
return
}
this.reallR()
},
reallR () {
this.zhud=true
this.loading=true
axios.post('https://www.daxunxun.com/users/register', {
username: this.tel,
password: this.password
}).then(res=>{
this.zhud=false
this.loading=false
if (res.data === 2) {
Toast('用户名已注册,请直接登录')
} else if (res.data === 0) {
Toast('注册失败')
} else {
Toast('注册成功')
}
})
}
}
}
</script> -
2. 登录
页面布局以及基本逻辑同注册基本相同,可直接复制注册,将相关注册字样更改为登录。删除相关的判断。更改相关函数。
-
<template>
<div class="container">
<header class="header">注册头部</header>
<div class="content">
<van-field
v-model="tel"
placeholder="请输入手机号"
:error-message="usertel"
clearable
/>
<van-field
v-model="password"
type="password"
placeholder="请输入密码"
:error-message="pass"
clearable
/>
<van-button type="primary" :loading="loading" loading-text="登录..." size="large" :disabled="zhud" @click="login">登录</van-button>
<van-divider @click="toRegister">去注册</van-divider>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import { Field,Button,Toast,Divider} from 'vant'
import axios from 'axios'
// import { setInterval, clearInterval } from 'timers';
// import func from '../../../vue-temp/vue-editor-bridge';
Vue.use(Field)
Vue.use(Button)
Vue.use(Toast)
Vue.use(Divider)export default {
data () {
return {
tel:'',
password:'',
zhud:false,
loading:false
}
},
computed: {
usertel () {
if (this.tel === ""){
return ''
}else if(!/^[1][3,4,5,7,8][0-9]{9}$/.test(this.tel)){
return '手机号格式错误'
}else {
return ''
}
},
pass () {
if (this.password === ""){
return ''
}else if(this.password.length<6){
return '密码不可小于6位'
}else {
return ''
}
}
},
methods: {
toRegister () {
this.$router.replace('/register')
},
login () {
if (this.tel === '' || this.usertel === '手机号码格式错误') {
Toast('手机号码输入有误')
return
}
if (this.password === '' || this.pass === '密码格式错误,最少为6位') {
Toast('密码输入有误')
return
}
if (this.sms === '' || this.sms !== this.adminCode) {
Toast('验证码输入有误')
return
}
this.reallR()
},
reallR () {
this.zhud=true
this.loading=true
axios.post('https://www.daxunxun.com/users/login', {
username: this.tel,
password: this.password
}).then(res=>{
this.zhud=false
this.loading=false
if (res.data === 2) {
Toast('用户未注册')
} else if(res.data === -1){
Toast('密码错误')
}else if (res.data === 0) {
Toast('登录失败')
} else {
Toast('登录成功')
localStorage.setItem('isLogin','ok') //登录标识
this.$router.back() //登陆成功返回上一页
}
})
}
}
}
</script> -
router.beforeEach((to,from,next)=>{
// console.log(to)
// console.log(from)
// next() //至此就可以显示页面了
//做业务逻辑,如果是登录状态,就进行下一步(注意登录页面不可做这个判断)
if(to.name = 'login'){ //如果要去的页面是登录页面,就进行下一步,不做判断
next()
}else{
if(localStorage.getItem('isLogin')==='ok'){
next()
}else{
next('/login')
}
} -
3.2 路由独享的导航守卫
路由独享的导航守卫—一般不推荐直接使用
比如在购物车路由下方加入下面一段代码,可以实现购物车页面的相关判断。
没有登录状态就直接去到登录页面,有登录状态就继续下一步。 -
beforeEnter (to,from,next) {
if(localStorage.getItem('isLogin')==="ok"){
next()
}else{
next('/login')
}
} -
3.3 组件内的导航守卫
先来简单看一下组件内的导航守卫相关介绍:
-
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
} -
beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
不过,你可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。
-
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
} - 本文以购物车页面为例,在路由进入之前,做一个判断,有登录状态进行下一步,没有登录状态就直接去到登录页面。组件内的导航守卫有两张写法,请看案例,且不同写法有不同的效果,按需而定
-
<template>
<div class="container">
<header class="header">购物车头部</header>
<div class="content">购物车内容</div>
</div>
</template>
<script>
export default {
beforeRouteEnter (to,from,next) {
// if (localStorage.getItem('isLogin')==='ok'){
// next()
// }else{
// next('/login') //这种登陆成功返回点击购物车之前的页面
// }
next(vm => {
if (localStorage.getItem('isLogin')==='ok'){
next()
}else{
// next('./login')
vm.$router.push('/login') //这种登录成功直接返回到了购物车
}
})
}
}
</script>