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>