Vue2积分商城PC端项目(二)

发布于:2022-11-03 ⋅ 阅读:(652) ⋅ 点赞:(0)

目录

一、登录模块布局

1.1、模态窗口的书写

1.2、设置点击展示模态窗口

扩展:namespaced:true

1.3、点击关闭模态窗口

1.4、点击标题栏的切换效果

1.5、表单基本布局

二、拼图验证滑块

2.1、安装插件

2.2、main.js入口文件引中入

2.3、在组件中使用

2.4、点击登录按钮,判断是否有进行拼图滑块验证

三、点击获取验证码按钮的逻辑

3.1、逻辑分析

3.2、点击获取验证码判断手机号格式

3.3、抽取工具函数(优化)

3.4、倒计时及其展示

3.5、发起获取验证码请求


一、登录模块布局

1.1、模态窗口的书写

点击登录按钮,弹出模态窗口,如下图:

在cpmonents目录下新建一个LoginBar.vue组件  

<template>
    <div class="modal">
        <div class="mask"></div>
        <div class="login-box">

        </div>
    </div>
</template>

<script>
export default {}
</script>
 
<style lang = "less" scoped>
    .modal{
        position: fixed;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
       /*  bottom: 0;
        right: 0; */
        .mask{
            width: 100%;
            height: 100%;
            background-color: rgba(0,0,0,.5);
        }
        .login-box{
            position:  absolute;
            left: 0;
            top: 0;
            bottom: 0;
            right: 0;
            margin:auto;
            width: 555px;
            height: 423px;
            background: url("../assets/img/login.png");
        }
    }
</style>

然后在App.vue组件中引入,注册,使用。

1.2、设置点击展示模态窗口

因为项目中可能有在各个组件中触发这个模态窗口的展示,所以控制模态框展示的变量可以放在Vuex中

在store中新建showModal目录,并在其中新建index.js:

export default{
    namespaced:true,
    // 以上的方式使其成为带命名空间的模块。保证在变量名一样的时候,添加一个父级名拼接。
    state:{
        isShowLoginModal:false//表示是够展示登录窗口
    },
    mutations:{
        // 修改isShowLoginModal的值
        changeIsShowLoginModal(state,payload){
            state.isShowLoginModal=payload
        }
    },
    actions:{

    },
}

扩展:namespaced:true

使用模块中的mutations、getters、actions时要加上模块名,例如使用commint执行mutations时

格式:模块名/模块中的mutations

xxx/setUserInfo

this.$store.commit(“userInfo/setUserInfo”,userInfo)

获取属性时同样加上模块名

格式:store.state.模块名.模块属性

$store.state.userInfo.userName

在store.js中引入:

import Vue from 'vue'
import Vuex from 'vuex'
import showModal from "./showModal"
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
    showModal
  }
})

LoginBar.vue组件中:

<script>
import {mapState} from "vuex"
export default {
    computed:{
        ...mapState({
            isShowLoginModal:state=>state.showModal.isShowLoginModal
        })
    }
}
</script>

HeaderBar.vue组件中:

<ul>
...
<li class="login-btn" @click="chanIsShowLoginModal(true)">登录</li>
</ul>
<script>
import {mapMutations} from "vuex"
export default {
    data () {},
    methods:{
        ...mapMutations({
            chanIsShowLoginModal:"showModal/chanIsShowLoginModal"
        })
    }
}
</script>

1.3、点击关闭模态窗口

LoginBar.vue中:

<template>
    <div class="modal" v-show="isShowLoginModal">
        <!--点击遮罩层也可以关闭模态窗口-->
        <div class="mask"  @click="chanIsShowLoginModal(false)"></div>
        <div class="login-box">
            <div class="close" @click="chanIsShowLoginModal(false)"></div>
        </div>
    </div>
</template>
<script>
import {mapState,mapMutations} from "vuex"
export default {
  	...
     methods:{
        ...mapMutations({
            chanIsShowLoginModal:"showModal/chanIsShowLoginModal"
        })
    }
}
</script>
<style lang = "less" scoped>
    .modal{
        ...
        .login-box{
           ...
            .close{
                width: 22px;
                height: 22px;
                background: url("../assets/img/close.png");
                position: absolute;
                right: 60px;
                top: 16px;
                cursor: pointer;
            }
        }
    }
</style>

1.4、点击标题栏的切换效果

LoginBar.vue中:

:class="isShowForm == true ? 'active' : ' ' "《等同》:class="{active:isShowForm}"

<ul class="title">
    <li @click="isShowForm=true"  :class="isShowForm == true ? 'active' : ''">手机号码登录</li>
    <li style="margin:0 10px">|</li>
    <li @click="isShowForm=false" :class="{active:!isShowForm}">微信扫码登录</li>
</ul>
<div class="body">
    <div class="form" v-show="isShowForm">
        表单
    </div>
    <div class="qrcode" v-show="!isShowForm">
        二维码
    </div>
</div>
<script>
export default {
    data () {
        return {
            isShowForm:true
        }
    }
    ...
}
</script>
<style lang = "less" scoped>
    .modal{
       ...
        .login-box{
    		...
            .title{
                display: flex;
                justify-content: center;
                width: 100%;
                padding-top: 50px;
                font-size:20px;
                color:#999;
                .active{
                    color:#333;
                }
            }
            .body{
                width: 355px;
                margin:20px auto 0;
                height:200px;
               
            }
        }
    }
</style>

1.5、表单基本布局

LoginBar.vue中:

<div class="body">
    <div class="form" v-show="isShowForm">
        <div class="mb20 row">
            <input type="text" class="ipt" placeholder="请输入手机号" v-model="phoneNum">
        </div>
        <div class="mb20 row">
            <input type="text" class="ipt" placeholder="请输入短信验证码">
            <div class="btn checkcode-btn">获取验证码</div>
        </div>
        <div class="mb20 btn">
            登录
        </div>
    </div>
    <div class="qrcode" v-show="!isShowForm">
        二维码
    </div>
</div>
<style>
    ...
			.title{
                display: flex;
                justify-content: center;
                width: 100%;
                padding-top: 50px;
                font-size:20px;
                color:#999;
                .active{
                    color:#333;
                }
            }
            .body{
                width: 355px;
                margin:20px auto 0;
                height:200px;
                
                .form{
                    .row{
                        flex:1;
                        display: flex;
                        
                    }
                    .ipt{
                        box-shadow: 0;
                        flex:1;
                        height: 48px;
                        border: 1px solid #e4e7eb;
                    }
                    .checkcode-btn{
                        width: 100px;
                        margin-left: 10px;
                    }
                    .btn{
                        background: #0a328e;
                        color: #fff;
                        text-align: center;
                        height: 50px;
                        line-height: 50px;
                        cursor: pointer;
                    }
                }
            }
</style>

二、拼图验证滑块

插件参考:vue-monoplasty-slide-verify: 基于滑动式的验证码,免于字母验证码的繁琐输入用于网页注册或者登录

2.1、安装插件

npm install --save vue-monoplasty-slide-verify
或者
yarn add vue-monoplasty-slide-verify

2.2、main.js入口文件引中入

import SlideVerify from 'vue-monoplasty-slide-verify' // 拼图验证码

Vue.use(SlideVerify)

2.3、在组件中使用

<template>
	<slide-verify :l="42" :r="20" :w="362" :h="140" @success="onSuccess" @fail="onFail" @refresh="onRefresh" :style="{ width: '100%' }" class="slide-box" ref="slideBlock" :slider-text="msg"></slide-verify>
</template>

样式和函数参照文档复制即可。

2.4、点击登录按钮,判断是否有进行拼图滑块验证

登录之前,我们需要验证用户是否有拼图验证过,有拼图验证过才可以登录。

我们以msg文字内容来判断是否有进行拼图滑块验证

<div class="mb20 btn" @click="submitFn">
    登录
</div>
...
<script>
    ...
	methods:{
       ...
        // 点击登录按钮
        submitFn() {
           	// 以msg文字内容来判断是否有进行拼图滑块验证
            if (this.msg == "再试一次" || this.msg == "向右滑动") {
                alert("请滑动拼图");
                return
            } 
           	alert("拼图滑块验证通过,可以执行登录了")
        },
    }
</script>

三、点击获取验证码按钮的逻辑

3.1、逻辑分析

可以正常获取验证码的前提是:手机号格式正确

所以,点击获取验证码的逻辑如下:

1、如果校验手机号格式不正确,则return

2、滑块拼图验证不通过,则return

3、验证成功后,发起请求,获取验证码成功,则进行倒计时

3.2、点击获取验证码判断手机号格式

<div class="btn checkcode-btn" @click="getCode">获取验证码</div>
...
<script>
    getCode(){
        // 1、验证手机号是否正确
        if(!/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/.test(this.phoneNum)){
            alert("请输入正确的手机号");
            return
        } 
        alert("手机号格式正确");
        
        // 2、进行滑块验证
           
        // 3、验证成功后,发起请求,获取验证码成功,则进行倒计时,并展示秒数
    },

</script> 

3.3、抽取工具函数(优化)

事实上,验证手机号本身是一个工具函数,和本身逻辑有关但是具体代码不需要在组件中体现。真实项目场景往往是放在工具函数的文件中。

src目录下新建utils文件夹,在里面新建index.js文件:

export const validateTelephoneNumber = value =>{
    let reg = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
    return reg.test(value)
}

在LoginBar.vue组件中:

import {validateTelephoneNumber} from "@/utils"
...
...

getCode(){
    // 1、验证手机号是否正确
    if(!validateTelephoneNumber(this.phoneNum)){
        alert("请输入正确的手机号");
        return
    }
    // 2、进行滑块验证
     	...      
    // 3、验证成功后,发起请求,获取验证码成功,则进行倒计时,并展示秒数
    	...

},

3.4、倒计时及其展示

连续点击倒计时会有bug,数字越跳越快,主要是重复开启倒计时造成的。

其实我们只需要把事件给到 "获取验证码" 所在的span,就可以解决

<div class="btn checkcode-btn">
    <span v-show="!isShowCount" @click="getCode">获取验证码</span>
	<span v-show="isShowCount">{{count}} s</span>
</div>
<script>
data () {
    return {
        // 是否展示表单的布尔值
        isShowForm:true,
        // 拼图滑块的文字
        msg: "向右滑动",
        // 用户手机号
        phoneNum:"",
        // 最大的计时时间
        countMax:60,
        // 倒计时时间,每秒变化的那个数字
        count:0,
        // 是否展示秒数所在盒子
        isShowCount:false
    }
},
...
...
countdown(){
    // 计时的方法
    // 倒计时,实际上就是每隔1秒,count减去1
    let timer = null;
    this.count = this.countMax;
    timer = setInterval(()=>{
        this.count--
        if(this.count===0){
            // 清除定时器 
            clearInterval(timer);
        }
    },1000);
}
</script>

3.5、发起获取验证码请求

接口: /sendSMS

api.js文件中

// 发送短信验证码请求
export const SendSMSAPI = params => request.post("/sendSMS",params);

在LoginBar.vue组件中:

// 短信验证码请求
import {SendSMSAPI} from "@/request/api"
   async  getCode(){
       // 1、验证手机号是否正确
       // 2、进行滑块验证      
       // alert("验证通过了,可以获取验证码");
            let res=await SendSMSAPI({
              // phone是接口的参数
              phone:this.phoneNum.trim()
            });
            console.log(res);//此时需要用到qs模块
            if(res.code==0){
            this.countdown();//进行倒计时,并展示秒数
            this.isShowCount=true;
            }else{
              alert(res.message)
            }
            // 3、验证成功后,发起请求,获取验证码成功,则进行倒计时,并展示秒数
    },

此时会报错,需要用到qs模块

拓展:qs模块:console.log(qs.stringify({name:'Vue'}));//"name=Vue"

安装qs模块: npm i qs

api.js中:

import qs from "qs"
// 发送短信验证码请求
export const SendSMSAPI = params => request.post("/sendSMS",qs.stringify(params));

注意:后端对每一个手机号做了限制,达到最大可发送短信条数,请隔数个小时后再尝试:

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到