Vue登录注册
- 注册
1.1 注册页面的布局
1.2 注册业务逻辑的实现
1.3封装api
- 登录
3.导航守卫
- 注册
1.1 注册页面的布局
需要用到Vant的Field组件
1.views下新建一个注册页面 ,完成基本布局。引入Vue和Field并使用。
3.给注册页面添加一个单独的路由,注册页面不需要底部。(注意,相关样式需要引入不同的组件,请细心查看官方文档,按需拿取内容)
- 利用计算属性给输入框做条件判断。本案例以手机号为例。
1.在views目录下创建三个文件
1.1、一个RetrievePass.vue文件写入注册的代码块
1.2、一个Register.vue文件写入手机验证码登录
1.3、一个Login.vue文件写入密码登录
RetrievePass.vue文件注册
<template> <!-- 注册 --> <div> <div class="zhx_retrieve"> <van-field v-model="sms" center clearable placeholder="请输入手机号"> <template #button> <a size="small" type="primary">发送验证码</a> </template> </van-field> <van-cell-group> <van-field v-model="sss" placeholder="请输入验证码" /> </van-cell-group> <van-cell-group> <van-field v-model="password" placeholder="请输入密码" /> </van-cell-group> </div> <div class="zhx_login_button"> <button>登录</button> </div> </div> </template> <script> export default { data() { return { sms: "", sss: "", password: "", }; }, }; </script> <style> .zhx_retrieve { width: 100%; height: 25vh; } .zhx_login_button { width: 100%; height: 10vh; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.8rem; } .zhx_login_button button { width: 90%; height: 7vh; background: orange; border-radius: 18px; border: none; } </style>
1.2 注册业务逻辑的实现
注:在此之前,记住要先去路由页面添加一个注册页面的路由。
1.补充了密码以及验证码的计算属性判断
密码:如果为空返回空,如果不符合正则,返回格式错误,否则表示可以直接返回空
验证码:如果为空返回空,否则不为五位,返回验证码格式错误,否则成功返回空
2.验证码
绑定点击事件senCode
将提示信息{{buttonmsg}}放在按钮内容中。
定义函数:(定时器注意用箭头函数)每一秒钟定义一次,先提前声明时间,在计时器内让时间减减,当时间为零时,清除定时器,同时btn的内容改为发送验证码,最后return。未return时,让按钮内的内容为时间减减+后重新发送(注意:在开启定时器时,要让按钮禁止点击,在清除定时器后再让按钮可点。)
Register.vue文件手机验证码登录
<template> <!-- 手机验证登录 --> <div> <div class="zhx_login_img"> <img src="../../assets/login/Login.png" alt="" /> </div> <div class="zhx_register"> <van-field v-model="sms" center clearable placeholder="请输入手机号"> <template #button> <a v-show="isShow == false" size="small" type="primary" @click="onClickSend" >发送验证码</a > <a v-show="isShow == true" >获取验证码({{ num }})</a > </template> </van-field> <van-cell-group> <van-field v-model="sss" placeholder="请输入验证码" /> </van-cell-group> </div> <div class="zhx_register_pass"> <span>*未注册的手机号将自动注册</span> <span @click="onLogin">使用密码登录</span> </div> <div class="zhx_login_button"> <button @click="redister">登录</button> </div> </div> </template> <script> import Vue from "vue"; import { Toast } from "vant"; Vue.use(Toast); export default { data() { return { sms: "", sss: "", isShow: false, num: 60, }; }, methods: { onLogin() { this.$router.push("/login"); }, onClickSend() { this.$APP .smsCode({ mobile: this.sms, sms_type: "login", }) .then((res) => { console.log(res); if (res.data.code === 200) { this.countDown(); Toast(res.data.msg); } else if (res.data.code == 201) { Toast(res.data.msg); } }); }, //倒计时 countDown() { this.isShow = true; setInterval(() => { this.num--; if (this.num <= 0) { this.isShow = false; this.num = 60; } }, 1000); }, redister() { this.$APP .login({ mobile: this.sms, sms_code: this.sss, client: 1, type: 2, }) .then((res) => { console.log(res); let token = res.data.data.remember_token; window.localStorage.setItem("token", token); this.$router.push("/home"); }); }, }, }; </script> <style scoped> .zhx_register { width: 100%; height: 15vh; } .zhx_login_img { width: 100%; height: 30vh; display: flex; align-items: center; justify-content: center; } .zhx_login_img img { width: 80%; } .zhx_login_button { width: 100%; height: 10vh; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.8rem; } .zhx_login_button button { width: 90%; height: 7vh; background: orange; border-radius: 18px; border: none; } .zhx_register_pass { width: 100%; height: 12vh; display: flex; justify-content: space-around; font-size: 0.6rem; color: gray; } </style>
Login.vue文件密码登录
<template> <!-- 密码登录 --> <div class="zhx_login"> <div class="zhx_login_img"> <img src="../../assets/login/Login.png" alt="" /> </div> <div> <van-form @submit="onSubmit"> <van-field v-model="username" name="用户名" placeholder="用户名" :rules="[{ required: true, message: \'请填写用户名\' }]" /> <van-field v-model="password" type="password" name="密码" placeholder="密码" :rules="[{ required: true, message: \'请填写密码\' }]" /> </van-form> </div> <div class="zhx_login_register"> <span @click="retrieve">找回密码</span> <div> <span @click="onRegister">注册/验证码登录</span> </div> </div> <div class="zhx_login_button"> <button @click="onClickLogin">登录</button> </div> </div> </template> <script> export default { data() { return { username: "", password: "", }; }, methods: { onSubmit(values) { console.log("submit", values); }, retrieve() { this.$router.push("/retrieve"); }, onRegister() { this.$router.push("/register"); }, //登录 onClickLogin() { this.$APP .login({ mobile: this.username, password: this.password, type: 1, }) .then((res) => { console.log(res); let token = res.data.data.remember_token; window.localStorage.setItem("token", token); console.log(res.data.data.is_new); this.$router.push("/home"); }); }, }, }; </script> <style scoped> .zhx_login { width: 100%; } .zhx_login_img { width: 100%; height: 30vh; display: flex; align-items: center; justify-content: center; } .zhx_login_img img { width: 80%; } .zhx_login_register { width: 100%; height: 10vh; display: flex; align-items: center; justify-content: space-around; font-size: 0.6rem; color: gray; } .zhx_login_button { width: 100%; height: 10vh; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.8rem; } .zhx_login_button button { width: 90%; height: 7vh; background: orange; border-radius: 18px; border: none; } </style>
在src里创建一个api文件写入三个js文件进行封装
1.1、一个core.js文件封装axios请求拦截和响应拦截
1.2、一个index.js文件封装请求的方法
1.3、一个path.js文件封装接口
core.jsaxios请求拦截和响应拦截
import axios from "axios" import apl from "./path" import { Loading } from \'element-ui\'; const instance = axios.create({ //axios创建的实例 baseURL: \'http://120.53.31.103:84\', // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。 timeout: 5000, // `timeout` 指定请求超时的毫秒数(0 表示无超时时间) 如果请求话费了超过 `timeout` 的时间,请求将被中断 headers: { \'X-Custom-Header\': \'foobar\' // `headers` 是即将被发送的自定义请求头 } }); var loading = null // 添加请求拦截器 instance.interceptors.request.use(function (config) { // 在发送请求之前做些什么 loading = Loading.service(); return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); }); // 添加响应拦截器 instance.interceptors.response.use(function (response) { // 对响应数据做点什么 setTimeout(function () { loading.close() }, 500) return response; }, function (error) { // 对响应错误做点什么 return Promise.reject(error); }); export function request(method, url, params) { //创建的request函数,把函数抛出 switch (method) { //switch判断 case apl.METHODS.GET: //当请求的方式为GET的时候, return get(url, params) //把get方式return出去 case apl.METHODS.POST: //当请求的方式为POST的时候, return post(url, params) //把post方式return出去 } } function get(url, params) { //封装的一个get函数 return instance.get(url, params) } function post(url, params) { //封装的一个post函数 return instance.post(url, params) }
index.js文件请求的方法
import { request } from "../apl/core" import apl from "../apl/path" const APP = { login(params) { return request(apl.METHODS.POST, apl.URL.Login, params); }, smsCode(params) { return request(apl.METHODS.POST, apl.URL.SmsCode, params); }, change(params) { return request(apl.METHODS.POST, apl.URL.Change, params); }, } export default APP
path.js文件接口
const apl = { METHODS: { GET: "get", //get请求 POST: "post" //post请求 }, //接口路径 URL: { //登录 Login: "/api/app/login", //验证码登录 SmsCode: "/api/app/smsCode", //修改密码 Change: "/api/app/password" } } export default apl
在router文件里配置需要的文件
import Vue from \'vue\' import VueRouter from \'vue-router\' Vue.use(VueRouter) const routes = [ { path: \'/\', name: \'Home\', component: () => import(\'../views/Home.vue\') }, { path: \'/login\', name: \'Login\', component: () => import(\'../views/login/Login.vue\') }, { path: \'/register\', name: \'Register\', component: () => import(\'../views/login/Register.vue\') }, { path: \'/retrievePass\', name: \'RetrievePass\', component: () => import(\'../views/login/RetrievePass.vue\') }, { path: \'/home\', name: \'Home\', component: () => import(\'../views/Home.vue\') } ] const router = new VueRouter({ // mode: \'history\', base: process.env.BASE_URL, routes }) export default router
在min.js里配置自己需要的组件
import Vue from \'vue\' import App from \'./App.vue\' import router from \'./router\' import store from \'./store\' import Vant from "vant" import "vant/lib/index.css" import axios from "axios" import ElementUI from \'element-ui\'; import \'element-ui/lib/theme-chalk/index.css\'; Vue.use(ElementUI); Vue.use(Vant) Vue.prototype.$axios = axios Vue.config.productionTip = false import APP from \'./apl/index\' Vue.prototype.$APP = APP; new Vue({ router, store, render: h => h(App) }).$mount(\'#app\')