21 登錄頁面(短信驗證倒計時,第三方登錄樣式渲染,狀態欄防遮擋組件)
一 簡單實現登錄頁面
效果圖:
要點:
1 input雖然是內聯元素,但是寬高 margin padding 全都有效。除了不換行和正常的塊狀元素區別不大
2 擴大點擊范圍可以考慮使用padding
3 可以考慮直接使用uni-status-bar/uni-status-bar.vue 組件來解決遮蓋狀態欄的問題。
<template>
<view>
<uni-status-bar></uni-status-bar>
<view class="iconfont font-weight-bold icon-guanbi flex align-center justify-center font-lg"
style="width: 100rpx; height: 100rpx;"
hover-class="text-muted"></view>
<!-- 賬號密碼登錄 -->
<template v-if="status">
<view class="font-lgger flex align-center justify-center" style="margin-top:100rpx;">
賬號密碼登錄
</view>
<view class="px-2">
<input class=" border-bottom font-md p-3" type="text"
style="margin-top:100rpx"
value="" placeholder="昵稱/手機號/郵箱" />
<!-- align-stretch直接保證了各個元素高度的統一,就不只是劇中對齊了 -->
<view class="flex align-stretch border-bottom ">
<input class="flex-1 font-md p-3" type="text"
value="" placeholder="請輸入密碼" />
<view class="text-muted flex align-center justify-center" style="width: 160rpx;">
忘記密碼
</view>
</view>
</view>
</template>
<template v-else>
<view class="font-lgger flex align-center justify-center" style="margin-top:100rpx;">
短信驗證碼登錄
</view>
<view class="px-2">
<view class="flex align-center border-bottom" style="margin-top:100rpx">
<view class="flex align-center justify-center font-weight-bold font-md">
+86
</view>
<input class="font-md p-3" type="text"
value="" placeholder="手機號" />
<!-- <view class="flex align-center justify-center font-weight-bold bg-main">
+86
</view> -->
</view>
<!-- align-stretch直接保證了各個元素高度的統一,就不只是劇中對齊了 -->
<view class="flex align-center border-bottom ">
<input class="flex-1 font-md p-3" type="text"
value="" placeholder="請輸入驗證碼" />
<view class="text-white rounded flex font-md p-1 align-center justify-center bg-main " style="width: 180rpx;">
獲取驗證碼
</view>
</view>
</view>
</template>
<view class="px-3 " style="padding-top:60rpx">
<button class="bg-main text-white" style="border-radius: 50rpx;border: 0;" type="primary">登錄</button>
</view>
<view class="flex align-center justify-center mx-2 my-2">
<view class="text-primary font py-2 mx-2 " @click="changeStatus">{{status?'短信驗證登錄':'賬號密碼登錄'}}</view>
<text>|</text>
<view class="text-primary font py-2 mx-2">登錄遇到問題</view>
</view>
<view class="flex align-center justify-center py-2">
<view class="" style="height: 1rpx;background-color: #CCCCCC;width: 100rpx;"></view>
<view class="text-muted font">
社交賬號登錄
</view>
<view class="" style="height: 1rpx;background-color: #CCCCCC;width: 100rpx;"></view>
</view>
<view class="flex align-center justify-between" style="padding:20rpx 100rpx">
<view class="iconfont icon-QQ bg-primary text-white font-lgger rounded-circle flex align-center justify-center" style="height:100rpx;width:100rpx;">
</view>
<view class="iconfont icon-QQ bg-primary text-white font-lgger rounded-circle flex align-center justify-center" style="height:100rpx;width:100rpx;">
</view>
<view class="iconfont icon-QQ bg-primary text-white font-lgger rounded-circle flex align-center justify-center" style="height:100rpx;width:100rpx;">
</view>
</view>
<view class="flex align-center justify-center mt-2">
<text class="text-muted font">注冊即代表您同意</text>
<text class="font text-primary">《xxx社區協議》</text>
</view>
</view>
</template>
<script>
import uniStatusBar from '@/components/uni-ui/uni-status-bar/uni-status-bar.vue'
export default {
components:{
uniStatusBar
},
data() {
return {
status:true
}
},
methods: {
changeStatus(){
this.status = !this.status
}
}
}
</script>
<style>
</style>
二 相對完善實現登錄頁面
效果圖:
要點:
1 完善了輸入框沒填滿內容,輸入框暗色無法點擊。
2 完善了發送驗證碼倒計時渲染。
3 完善並且封裝了部分第三方登錄的渲染樣式。
代碼:
<template>
<view>
<!-- 狀態欄占位 -->
<uni-status-bar></uni-status-bar>
<!-- 左上角的叉 -->
<view class="iconfont font-weight-bold icon-guanbi flex align-center justify-center font-lg"
style="width: 100rpx; height: 100rpx;"
hover-class="text-muted"
@click="back"></view>
<!-- 賬號密碼登錄 -->
<template v-if="status">
<view class="font-lgger flex align-center justify-center" style="margin-top:100rpx;">
賬號密碼登錄
</view>
<view class="px-2">
<input class=" border-bottom font-md p-3" type="text"
style="margin-top:100rpx"
value="" placeholder="昵稱/手機號/郵箱"
v-model="username"/>
<!-- align-stretch直接保證了各個元素高度的統一,就不只是劇中對齊了 -->
<view class="flex align-stretch border-bottom ">
<input class="flex-1 font-md p-3" type="text"
value="" placeholder="請輸入密碼"
v-model="password"/>
<view class="text-muted flex align-center justify-center" style="width: 160rpx;">
忘記密碼
</view>
</view>
</view>
</template>
<!-- 短信驗證登錄 -->
<template v-else>
<view class="font-lgger flex align-center justify-center" style="margin-top:100rpx;">
短信驗證碼登錄
</view>
<view class="px-2">
<!-- 手機號 -->
<view class="flex align-center border-bottom" style="margin-top:100rpx">
<view class="flex align-center justify-center font-weight-bold font-md">
+86
</view>
<input class="font-md p-3" type="text"
value="" placeholder="手機號"
v-model="phone"/>
<!-- <view class="flex align-center justify-center font-weight-bold bg-main">
+86
</view> -->
</view>
<!-- 驗證碼 -->
<!-- align-stretch直接保證了各個元素高度的統一,就不只是劇中對齊了 -->
<view class="flex align-center border-bottom ">
<input class="flex-1 font-md p-3" type="text"
value="" placeholder="請輸入驗證碼"
v-model="code"/>
<view class="text-white rounded flex font-md p-1 align-center justify-center bg-main " style="width: 180rpx;"
@click="getCode"
:class="codeTime>0 ?'bg-main-disabled':'bg-main'">
{{codeTime>0 ? codeTime: '獲取驗證碼'}}
</view>
</view>
</view>
</template>
<!-- 登錄按鈕 -->
<view class="px-3 " style="padding-top:60rpx">
<button class=" text-white" style="border-radius: 50rpx;border: 0;" type="primary"
:disabled="disabled"
:class="disabled?'bg-main-disabled':'bg-main'"
@click="submit">登錄</button>
</view>
<view class="flex align-center justify-center mx-2 my-2">
<view class="text-primary font py-2 mx-2 " @click="changeStatus">{{status?'短信驗證登錄':'賬號密碼登錄'}}</view>
<text>|</text>
<view class="text-primary font py-2 mx-2">登錄遇到問題</view>
</view>
<view class="flex align-center justify-center py-2">
<view class="" style="height: 1rpx;background-color: #CCCCCC;width: 100rpx;"></view>
<view class="text-muted font">
社交賬號登錄
</view>
<view class="" style="height: 1rpx;background-color: #CCCCCC;width: 100rpx;"></view>
</view>
<!-- 其他登錄方式 -->
<other-login></other-login>
<view class="flex align-center justify-center mt-2">
<text class="text-muted font">注冊即代表您同意</text>
<text class="font text-primary">《xxx社區協議》</text>
</view>
<!-- <view class="">
</view> -->
</view>
</template>
<script>
import uniStatusBar from '@/components/uni-ui/uni-status-bar/uni-status-bar.vue'
import otherLogin from '@/components/common/outer-login.vue'
export default {
components:{
uniStatusBar,
otherLogin
},
data() {
return {
status:true,
username:"",
password:"",
phone:"",
code:"",
codeTime:0
}
},
computed:{
disabled(){
if((this.username===''||this.password==='')&&(this.phone===''||this.code==='')){
return true
}
return false
}
},
methods: {
// 后退1頁
back(){
uni.navigateBack({
delta:1
})
},
// 初始化表單
initForm(){
this.username = ''
this.password = ''
this.phone = ''
this.code = ''
},
// 切換賬號密碼登錄or短信登錄
changeStatus(){
this.status = !this.status
},
// 獲取驗證碼
getCode(){
// 防止重復獲取
if (this.codeTime>0){
return;
}
// 倒計時
this.codeTime = 5
// 箭頭函數可以直接拿到外面的this的內容
let timer = setInterval(()=>{
if (this.codeTime >= 1){
this.codeTime--
} else{
clearInterval(timer)
}
},1000)
},
// 表單驗證
validate(){
//手機號正則 只是針對驗證碼的手機號字段,其他並未做兼容。
var mPattern = /^1[34578]\d{9}$/;
if (!mPattern.test(this.phone)) {
uni.showToast({
title: '手機號格式不正確',
icon: 'none'
});
return false
}
// ...更多驗證
return true
},
// 提交
submit(){
// 表單驗證
if (!this.validate()) return;
// 提交后端
// 登錄成功處理
}
}
}
</script>
<style>
</style>
Components/common/outer-login.vue
<template>
<view>
<view class="flex align-center justify-between" style="padding:20rpx 100rpx">
<view
v-for="(item,index) in providerList" :key="index"
class="iconfont text-white font-lgger rounded-circle flex align-center justify-center"
style="height:100rpx;width:100rpx;"
:class="item.icon+' '+item.bgColor">
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
providerList:[]
}
},
mounted() {
uni.getProvider({
service: 'oauth',
success: (result) => {
console.log(result.provider)
this.providerList = result.provider.map((value) => {
// 注釋
// [weixin,qq,sinaweibo] 通過map函數變成
// [{
// providerName = '微信登錄'
// icon : 'icon-weixin'
// bgColor :'bg-success'
// },
// {},{}.....]
let providerName = '';
let icon = ''
let bgColor = ''
switch (value) {
case 'weixin':
providerName = '微信登錄'
// 自己在這個位置添加上需要渲染的信息 如 icon bgColor
icon = 'icon-weixin'
bgColor = 'bg-success'
break;
case 'qq':
providerName = 'QQ登錄'
icon = 'icon-QQ'
bgColor = 'bg-primary'
break;
case 'sinaweibo':
providerName = '新浪微博登錄'
icon = 'icon-xinlangweibo'
bgColor = 'bg-warning'
break;
}
// 返回的時候
return {
name: providerName,
id: value,
icon:icon,
bgColor:bgColor
}
});
},
fail: (error) => {
console.log('獲取登錄通道失敗', error);
}
});
},
methods: {
}
}
</script>
<style>
</style>