登陆和注册界面开发

1.路由守卫实现基础校验功能

(1)在router文件夹下面的index.js文件中,写入

beforeEnter(to,from,next){
      const {isLogin} =localStorage;
      isLogin ? next({name:"Home"}) : next();
},

(2)使用axios发送登陆mock请求
将请求函数进行封装,在src建立一个utils文件夹,在utils文件夹下创建一个request.js文件
request.js

import axios from 'axios';

const instance = axios.create({
    baseURL:'https://www.fastmock.site/mock/ae8e9031947a302fed5f92425995aa19/jd',
    timeout:10000
})

export const get = (url,params = {})=>{
    return new Promise((resolve,reject) => {
        instance.get(url,{params}).then((response)=>{
            resolve(response.data)
        },err=>{
            reject(err)
        })
    })
}
export const post = (url,data = {})=>{
        return new Promise((resolve,reject) => {
            instance.post(url,data,{
                headers:{
                    'Content-Type':'application/json'
                }
            }).then((response)=>{
                resolve(response.data)
            },err=>{
                reject(err)
            })
        })
}

登陆请求跳转到首页的函数

const handleLogin= async ()=>{
        try{
            const result = await post('/api/user/login',{
                username:data.username,
                password:data.password
            })
            if(result?.errno === 0){
                localStorage.isLogin=true;
                    router.push({name:'Home'});
            }else{
                showToast("登陆失败")
            }
        }catch(e){
            showToast("请求失败")
        }         
    }

弹窗组件的开发ToastV.vue

<template>
    <div class="toast">{{message}}</div>
</template>

<script>
import { reactive,toRefs } from 'vue';
export default {
    props:["message"],
    setup() {
        
    },
}
export const useToastEffect = ()=>{
    const toastData = reactive({
        show:false,
        toastMessage:''
    });
    const showToast = (message)=>{
        toastData.show=true;
        toastData.toastMessage=message;
        setTimeout(()=>{
            toastData.show=false;
            toastData.toastMessage='';
        },3000)
    }
    const { show,toastMessage } = toRefs(toastData);
    return {show,toastMessage,showToast}
}
</script>

<style lang="scss" scoped>
@import '../style/viriables.scss';
.toast{
    position: fixed;
    left: 50%;
    top:50%;
    transform: translate(-50%,-50%);
    padding: .1rem;
    background: rgba(0,0,0,.35);
    border-radius: .05rem;
    color: $bgColor;
}
</style>

2.整体代码如下

LoginV.vue

<template>
    <div class="wrapper">
        <img class="wrapper__img" src="http://www.dell-lee.com/imgs/vue3/user.png" />
        <div class="wrapper__input">
            <input 
            class="wrapper__input__content" 
            placeholder="请输入用户名"
            v-model="username"
            />
        </div>
        <div class="wrapper__input">
            <input
             class="wrapper__input__content"
             placeholder="请输入密码" 
             type="password"
             v-model="password"
             autocomplete="new-password"
             />
        </div>
        <div class="wrapper__login-button" @click="handleLogin">登陆</div>
        <div class="wrapper__login-link" @click="handleRegisterClick">立即注册</div>
        <ToastV v-if="show" :message="toastMessage" />
    </div>
</template>

<script>
import {useRouter} from 'vue-router';
import {post} from '../../utils/request'
import { reactive,toRefs } from 'vue';
import ToastV,{useToastEffect} from '../../components/ToastV.vue'

const useLoginEffect = (showToast)=>{
    const router = useRouter();
    const data = reactive({ username:'', password:'', });
    const handleLogin= async ()=>{
        try{
            const result = await post('/api/user/login',{
                username:data.username,
                password:data.password
            })
            if(result?.errno === 0){
                localStorage.isLogin=true;
                    router.push({name:'Home'});
            }else{
                showToast("登陆失败")
            }
        }catch(e){
            showToast("请求失败")
        }         
    }
    const { username,password } = toRefs(data);
    return {username,password,handleLogin}
}

const useRegisterEffect = ()=>{
    const router = useRouter();
    const handleRegisterClick = ()=>{
           router.push({name:"Register"});
    }
    return {handleRegisterClick}
}

export default {
    name:'LoginV',
    components:{ToastV},
    //职责就是告诉你,代码执行的流程
    setup() {  
        const {show,toastMessage,showToast} = useToastEffect();
        const {username,password,handleLogin} = useLoginEffect(showToast);
        const {handleRegisterClick} = useRegisterEffect();
        
        return{
           username,password,show,toastMessage,
           handleLogin,handleRegisterClick,
        }
    },
}
</script>

<style lang="scss" scoped>
@import '../../style/viriables.scss';
.wrapper{
    position:absolute;
    top: 50%;
    left: 0;
    right: 0;
    transform: translateY(-50%);
    &__img{
        display: block;
        margin: 0 auto .4rem auto;
        width: .66rem;
        height: .66rem;
    }
    &__input{
        box-sizing: border-box;
        height: .48rem;
        margin: 0 .4rem .16rem .4rem;
        padding: 0 .16rem;
        background: #F9F9F9;
        border: .01rem solid rgba(0,0, 0 ,0.10);
        border-radius: .06rem;
        &__content{
            margin-top: .12rem;
            line-height: .22rem;
            border: none;
            outline: none;
            width: 100%;
            background: none;
            font-size: .16rem;
            color:$content-notice-fontcolor;
            &::placeholder{
                color:$content-notice-fontcolor;
            } 
        }    
    }
    &__login-button{
        margin: .32rem .4rem .16rem .4rem;
        line-height: .48rem;
        font-size: .16rem;
        background: $btn-bgColor;
        box-shadow: 0 .04rem .08rem 0 rgba( 0, 145,255,0.32);
        border-radius: .04rem;
        color: $bgColor;
        text-align: center;
    }
    &__login-link{
        text-align: center;
        font-size: .14rem;
        color: $content-notice-fontcolor ;
    }
}
</style>

注册界面RegisterV.Vue

<template>
    <div class="wrapper">
        <img class="wrapper__img" src="http://www.dell-lee.com/imgs/vue3/user.png" />
        <div class="wrapper__input">
            <input 
            class="wrapper__input__content" 
            placeholder="请输入用户名"
            v-model="username"
            />
        </div>
        <div class="wrapper__input">
            <input
             class="wrapper__input__content"
             placeholder="请输入密码" 
             type="password"
             autocomplete="new-password"
             v-model="password"
             />
        </div>
        <div class="wrapper__input">
            <input
             class="wrapper__input__content"
             placeholder="确认密码" 
             type="password"
             v-model="ensurement"
             />
        </div>
        <div class="wrapper__register-button" @click="handleRegister">注册</div>
        <div class="wrapper__register-link" @click="handleLoginClick">已有账号去登陆</div>
        <ToastV v-if="show" :message="toastMessage" />
    </div>
</template>

<script>
import {useRouter} from "vue-router";
import { reactive,toRefs } from 'vue';
import {post} from '../../utils/request';
import ToastV,{useToastEffect} from '../../components/ToastV.vue'
//注册相关逻辑
const useRegisterEffect = (showToast)=>{
    const router = useRouter();
    const data = reactive({ username:'', password:'',ensurement:'' });
    const handleRegister= async ()=>{
        try{
            const result = await post('/api/user/register',{
                username:data.username,
                password:data.password
            })
            if(result?.errno === 0){
                router.push({name:'Login'});
            }else{
                showToast("注册失败")
            }
            }catch(e){
                showToast("请求失败")
            }         
       }
    const { username,password,ensurement } = toRefs(data);
    return {username,password,ensurement,handleRegister}
}
export default {
    name:'RegisterV',
    components:{ToastV},
    setup() {
        const router = useRouter();
        const {show,toastMessage,showToast} = useToastEffect();
        const { username,password,ensurement,handleRegister} = useRegisterEffect(showToast);
        const handleLoginClick = ()=>{
          router.push({name:"Login"});
        }
        return {
            username,password,ensurement,show,toastMessage,
            handleRegister,handleLoginClick
            }
    },
}
</script>

<style lang="scss" scoped>
@import '../../style/viriables.scss';
.wrapper{
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    transform: translateY(-50%);
    &__img{
        display: block;
        margin: 0 auto .4rem auto;
        width: .66rem;
        height: .66rem;
    }
    &__input{
        box-sizing: border-box;
        height: .48rem;
        margin: 0 .4rem .16rem .4rem;
        padding: 0 .16rem;
        background: #F9F9F9;
        border: .01rem solid rgba(0,0, 0 ,0.10);
        border-radius: .06rem;
        &__content{
            line-height: .48rem;
            border: none;
            outline: none;
            width: 100%;
            background: none;
            font-size: .16rem;
            color:$content-notice-fontcolor;
            &::placeholder{
                color:$content-notice-fontcolor;
            } 
        }    
    }
    &__register-button{
        margin: .32rem .4rem .16rem .4rem;
        line-height: .48rem;
        font-size: .16rem;
        background: $btn-bgColor;
        box-shadow: 0 .04rem .08rem 0 rgba( 0, 145,255,0.32);
        border-radius: .04rem;
        color: $bgColor;
        text-align: center;
    }
    &__register-link{
        text-align: center;
        font-size: .14rem;
        color: $content-notice-fontcolor ;
    }
}
</style>

通过代码拆分可提高代码的维护性,将代码封装好放入script内,在setup中引用
setup函数职责就是告诉你,代码执行的流程

登陆和注册界面实现

登陆界面.png
注册界面.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,914评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,935评论 2 383
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,531评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,309评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,381评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,730评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,882评论 3 404
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,643评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,095评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,448评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,566评论 1 339
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,253评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,829评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,715评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,945评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,248评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,440评论 2 348

推荐阅读更多精彩内容