赞
踩
登录页
1、为了方便起见,先将element-ui的使用改为全局引入的方式。修改main.js文件如下:
- import Vue from 'vue'
- import App from './App.vue'
- import ElementUI from 'element-ui'
- import 'element-ui/lib/theme-chalk/index.css'
- //这个是局部引入,前面的文章有讲过
- // import '../plugins/element'
- import 'font-awesome/css/font-awesome.min.css'
- import axios from 'axios'
- import router from './router/index'
- Vue.config.productionTip = false
- Vue.prototype.axios = axios
- Vue.use(ElementUI)
- new Vue({
- router,
- render: h => h(App),
- }).$mount('#app')
2、写登陆页面:
2.1、components文件夹下新建Login.vue
2.2、从element-ui官网找需要的组件:+
2.3、修改代码(包括数据和表单绑定)整合后:
- <template>
- <div class="login">
- <el-card class="box-card">
- <div slot="header" class="clearfix">
- <span>疫起健康后台管理系统</span>
- </div>
- <el-form
- :model="loginForm"
- ref="loginForm"
- label-width="100px"
- >
- <el-form-item label="用户名" prop="username">
- <el-input
- v-model="loginForm.username"
- autocomplete="off"
- ></el-input>
- </el-form-item>
- <el-form-item label="密码" prop="password">
- <el-input
- type="password"
- v-model="loginForm.password"
- autocomplete="off"
- ></el-input>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="submitForm('loginForm')"
- >登录</el-button>
- <el-button @click="resetForm('loginForm')">重置</el-button>
- </el-form-item>
- </el-form>
- </el-card>
- </div>
- </template>
-
- <script>
- export default {
- data() {
- return{
- loginForm:{
- username:'',
- password:''
- }
- }
- },
- };
- </script>
-
- <style lang="scss">
- .login{
- width: 100%;
- height: 100%;
- position:absolute;
- background: #88b2dc;
- .box-card{
- width: 450px;
- margin: 160px auto;
- .el-card__header{
- font-size: 34px;
- }
- .el-button{
- width: 30%;
- }
- }
- }
- </style>
3、修改路由:启动项目(使用重定向)和输入http://localhost/login,进入的页面都是为登录页面
- import Vue from 'vue'
- import Router from 'vue-router'
- //import Home from '../components/Home.vue'
-
- Vue.use(Router)
-
- export default new Router({
- routes: [
- {
- path: '/',
- // component: Home
- redirect:'/login',
- component: () => import('@/components/Login') //路由懒加载
- //component: resolve => require(['@/components/Home'], resolve) //异步加载
- },
- {
- path: '/login',
- name:'Login',
- component: () => import('@/components/Login') //路由懒加载
- //component: resolve => require(['@/components/Home'], resolve) //异步加载
- },
- {
- path: '/home',
- // component: Home
- component: () => import('@/components/Home') //路由懒加载
- //component: resolve => require(['@/components/Home'], resolve) //异步加载
- }
- ],
- mode: 'history'
- })
运行结果:
4、登录验证
4.1 简易版,适用于小项目和简单的验证规则,实现:将验证规则直接写在html中
- <template>
- <div class="login">
- <el-card class="box-card">
- <div slot="header" class="clearfix">
- <span>疫起健康后台管理系统</span>
- </div>
- <el-form :model="loginForm" ref="loginForm" label-width="100px">
- <el-form-item
- label="用户名"
- prop="username"
- :rules="[
- { required: true, message: '请输入用户名', trigger: 'blur' },
- {
- min: 4,
- max: 10,
- message: '长度在4-10位字符之间',
- trigger: 'blur',
- },
- ]"
- >
- <el-input v-model="loginForm.username" autocomplete="off"></el-input>
- </el-form-item>
- <el-form-item
- label="密码"
- prop="password"
- :rules="[
- { required: true, message: '请输入密码', trigger: 'blur' },
- {
- min: 6,
- max: 12,
- message: '长度在6-12位字符之间',
- trigger: 'blur',
- },
- ]"
- >
- <el-input
- type="password"
- v-model="loginForm.password"
- autocomplete="off"
- ></el-input>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="login('loginForm')"
- >登录</el-button
- >
- <el-button @click="resetForm('loginForm')">重置</el-button>
- </el-form-item>
- </el-form>
- </el-card>
- </div>
- </template>
当输入框失去焦点时,会自动进行表单校验
4.2登录验证进阶版
①在表单里绑定rules,直接在Login.vue页面的data中写校验规则,写法参考element-ui的form表单
- <template>
- <div class="login">
- <el-card class="box-card">
- <div slot="header" class="clearfix">
- <span>疫起健康后台管理系统</span>
- </div>
- <el-form
- :model="loginForm"
- ref="loginForm"
- label-width="100px"
- :rules="rules"
- >
- <el-form-item label="用户名" prop="username">
- <el-input v-model="loginForm.username" autocomplete="off"></el-input>
- </el-form-item>
- <el-form-item label="密码" prop="password">
- <el-input
- type="password"
- v-model="loginForm.password"
- autocomplete="off"
- ></el-input>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="login('loginForm')">登录</el-button>
- <el-button @click="resetForm('loginForm')">重置</el-button>
- </el-form-item>
- </el-form>
- </el-card>
- </div>
- </template>
-
- <script>
- export default {
- data() {
- // rule 是校验规则,value是input用户输入的值,callback是回调函数 参考element-ui的api文档
- const validateName = (rule, value, callback) => {
- // 请输入4-10位昵称
- let reg = /(^[a-zA-Z0-9]{4,10}$)/;
- if (value === "") {
- callback(new Error("请输入用户名"));
- } else if (!reg.test(value)) {
- callback(new Error("请输入4-10位用户名"));
- } else {
- callback();
- }
- };
- const validatePass = (rule, value, callback) => {
- // 6-12位密码需要包含大小写字母和数字以及特殊符号
- let pass =
- /^\S*(?=\S{6,12})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/;
- if (value === "") {
- callback(new Error("请输入密码"));
- } else if (!pass.test(value)) {
- callback(new Error("6-12位密码需要包含大小写字母和数字及特殊符号"));
- } else {
- callback();
- }
- };
- return {
- loginForm: {
- username: "",
- password: "",
- },
- rules: {
- username: [{ validator: validateName, trigger: "blur" }],
- password: [{ validator: validatePass, trigger: "blur" }],
- },
- };
- },
-
- methods: {
- login(loginForm) {
- this.$refs[loginForm].validate((valid) => {
- if (valid) {
- console.log(this.loginForm);
- } else {
- console.log(this.loginForm);
- }
- });
- },
- resetForm(loginForm) {
- this.$refs[loginForm].resetFields();
- },
- },
- };
- </script>
-
- <style lang="scss">
- .login {
- width: 100%;
- height: 100%;
- position: absolute;
- background: #88b2dc;
- .box-card {
- width: 450px;
- margin: 160px auto;
- .el-card__header {
- font-size: 34px;
- }
- .el-button {
- width: 30%;
- }
- }
- }
- </style>
效果:
小技巧:使用写校验规则插件
使用:按下f1(我的笔记本需要按下Fn+f1)
②在表单里绑定rules,校验规则封装后,再在Login.vue页面导入校验规则(更推荐)
在src下新建utlis文件夹,新建validate.js文件,把Login.vue页面data中的校验规则过来,修改为如下:
- // 用户名匹配
- export function nameRule(rule, value, callback) {
- // 请输入4-10位昵称
- let reg = /(^[a-zA-Z0-9]{4,10}$)/;
- if (value === "") {
- callback(new Error("请输入用户名"));
- } else if (!reg.test(value)) {
- callback(new Error("请输入4-10位用户名"));
- } else {
- callback();
- }
- }
-
- // 密码正则匹配
- export function passRule(rule, value, callback) {
- // 6-12位密码需要包含大小写字母和数字以及特殊符号
- let pass = /^\S*(?=\S{6,12})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/;
- if (value === "") {
- callback(new Error("请输入密码"));
- } else if (!pass.test(value)) {
- callback(new Error("6-12位密码需要包含大小写字母和数字及特殊符号"));
- } else {
- callback();
- }
- }
在Login.vue页面修改为:
- <template>
- <div class="login">
- <el-card class="box-card">
- <div slot="header" class="clearfix">
- <span>疫起健康后台管理系统</span>
- </div>
- <el-form
- :model="loginForm"
- ref="loginForm"
- label-width="100px"
- :rules="rules"
- >
- <el-form-item label="用户名" prop="username">
- <el-input v-model="loginForm.username" autocomplete="off"></el-input>
- </el-form-item>
- <el-form-item label="密码" prop="password">
- <el-input
- type="password"
- v-model="loginForm.password"
- autocomplete="off"
- ></el-input>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="login('loginForm')">登录</el-button>
- <el-button @click="resetForm('loginForm')">重置</el-button>
- </el-form-item>
- </el-form>
- </el-card>
- </div>
- </template>
-
- <script>
- import { nameRule, passRule } from '../utils/validate.js'
-
- export default {
- data() {
- return {
- loginForm: {
- username: "",
- password: "",
- },
- rules: {
- username: [{ validator: nameRule, trigger: "blur" }],
- password: [{ validator: passRule, trigger: "blur" }],
- },
- };
- },
-
- methods: {
- login(loginForm) {
- this.$refs[loginForm].validate((valid) => {
- if (valid) {
- console.log(this.loginForm);
- this.axios
- .post("http://1.116.64.64:5004/api2/login", this.loginForm)
- .then((res) => {
- console.log(res);
- if (res.data.status === 200) {
- localStorage.setItem("username", res.data.username);
- this.$message({ message: res.data.message, type: "success" });
- this.$router.push("/home");
- }
- })
- .catch((err) => {
- console.error(err);
- });
- } else {
- console.log(this.loginForm);
- }
- });
- },
- resetForm(loginForm) {
- this.$refs[loginForm].resetFields();
- },
- },
- };
- </script>
-
- <style lang="scss">
- .login {
- width: 100%;
- height: 100%;
- position: absolute;
- background: #88b2dc;
- .box-card {
- width: 450px;
- margin: 160px auto;
- .el-card__header {
- font-size: 34px;
- }
- .el-button {
- width: 30%;
- }
- }
- }
- </style>
效果:
5、登录页面连接后端
第一种
首先:使用mock准备模拟一下网络请求后端接口:
① 在vscode终端输入,ctrl+c结束正在运行的项目,再下载mock插件,输入
npm i @shymean/mock-server -g
② 插件安装完成后,然后在磁盘中随便一个地方新建一个文件夹,命名为 mock; 在mock文件里面新建一个mock.js空文件;
在终端进入mock文件夹,输入命令mock,启动本地mock服务器,默认端口为7654
mock>mock server listen at 7654
操作步骤如下图:
打开mock.js这个文件,自己写一些测试数据如下:
- //登录接口
- Mock.mock(/login/, {
- code: 200,
- data: {
- access_token: "748_bef_246_test",
- expires_in: 7200,
- }
- })
-
- //用户信息
- Mock.mock(/userInfo/, {
- code: 200,
- user: {
- userName:'admin',
- password:'123456',
- role:'admim',
- }
- })
第二种
找一个自己或别人写好的后端接口,B站有很多,找一下直接用
封装token
在utils文件夹下新建setToken.js文件,内容如下:
- export function setToken(tokenKey, token) {
- return localStorage.setItem(tokenKey, token)
- }
-
- export function getToken(tokenKey) {
- return localStorage.getItem(tokenKey)
- }
-
- export function removeToken(tokenKey) {
- return localStorage.removeItem(tokenKey)
- }
在Login.vue进行导入使用
- <template>
- <div class="login">
- <el-card class="box-card">
- <div slot="header" class="clearfix">
- <span>疫起健康后台管理系统</span>
- </div>
- <el-form
- :model="loginForm"
- ref="loginForm"
- label-width="100px"
- :rules="rules"
- >
- <el-form-item label="用户名" prop="username">
- <el-input v-model="loginForm.username" autocomplete="off"></el-input>
- </el-form-item>
- <el-form-item label="密码" prop="password">
- <el-input
- type="password"
- v-model="loginForm.password"
- autocomplete="off"
- ></el-input>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="login('loginForm')">登录</el-button>
- <el-button @click="resetForm('loginForm')">重置</el-button>
- </el-form-item>
- </el-form>
- </el-card>
- </div>
- </template>
-
- <script>
- import { nameRule, passRule } from '../utils/validate.js'
- import { setToken } from '@/utils/setToken.js'
- export default {
- data() {
- return {
- loginForm: {
- username: "",
- password: "",
- },
- rules: {
- username: [{ validator: nameRule, trigger: "blur" }],
- password: [{ validator: passRule, trigger: "blur" }],
- },
- };
- },
-
- methods: {
- login(loginForm) {
- this.$refs[loginForm].validate((valid) => {
- if (valid) {
- console.log(this.loginForm);
- this.axios
- .post("http://1.116.64.64:5004/api2/login", this.loginForm)
- .then((res) => {
- console.log(res);
- if (res.data.status === 200) {
- // localStorage.setItem("username", res.data.username);
- setToken("username", res.data.username);
- this.$message({ message: res.data.message, type: "success" });
- this.$router.push("/home");
- }
- })
- .catch((err) => {
- console.error(err);
- });
- } else {
- console.log(this.loginForm);
- }
- });
- },
- resetForm(loginForm) {
- this.$refs[loginForm].resetFields();
- },
- },
- };
- </script>
-
- <style lang="scss">
- .login {
- width: 100%;
- height: 100%;
- position: absolute;
- background: #88b2dc;
- .box-card {
- width: 450px;
- margin: 160px auto;
- .el-card__header {
- font-size: 34px;
- }
- .el-button {
- width: 30%;
- }
- }
- }
- </style>
连接后端登录接口,二次封装axios
设置项目代理,修改vue.config.js文件如下:
- const { defineConfig } = require('@vue/cli-service')
- module.exports = defineConfig({
- transpileDependencies: true,
- devServer: {
- open: true,
- host: 'localhost',
- proxy: {
- '/api': {
- target: 'http://1.116.64.64:5004/api2/',
- changeOrigin: true,
- pathRewrite: {
- '^/api': ''
- }
- }
-
- }
- }
- })
项目根目录下新建service.js文件,进行封装axios
- import axios from 'axios'
- import { getToken } from '@/utils/setToken.js'
- import { Message } from 'element-ui'
-
- const service = axios.create({
- baseURL: '/api', // baseURL会自动加在请求地址上
- timeout: 3000
- })
-
- // 添加请求拦截器
- service.interceptors.request.use((config) => {
- // 在请求之前做些什么(获取并设置token)
- config.headers['token'] = getToken('token')
- return config
- }, (error) => {
- return Promise.reject(error)
- })
-
- // 添加响应拦截器
- service.interceptors.response.use((response) => {
- // 对响应数据做些什么
- let { status, message } = response.data
- if(status !== 200) {
- Message({message: message || 'error', type: 'warning'})
- }
- return response
- }, (error) => {
- return Promise.reject(error)
- })
-
- export default service
使用二次封装的axios,依旧采用全局导入的方式,修改main.js文件如下:
- import Vue from 'vue'
- import App from './App.vue'
- import ElementUI from 'element-ui'
- import 'element-ui/lib/theme-chalk/index.css'
- // import '../plugins/element'
- import 'font-awesome/css/font-awesome.min.css'
- // import axios from 'axios'
- import service from '../service'
- import router from './router/index'
- //或者这样导入:会自动找到index文件
- //import router from './router'
- Vue.config.productionTip = false
- // Vue.prototype.axios = axios
- Vue.prototype.service = service
- Vue.use(ElementUI)
- new Vue({
- router,
- render: h => h(App),
- }).$mount('#app')
修改Login.vue页面,注释掉引入的setToken文件
- <template>
- <div class="login">
- <el-card class="box-card">
- <div slot="header" class="clearfix">
- <span>疫起健康后台管理系统</span>
- </div>
- <el-form
- :model="loginForm"
- ref="loginForm"
- label-width="100px"
- :rules="rules"
- >
- <el-form-item label="用户名" prop="username">
- <el-input v-model="loginForm.username" autocomplete="off"></el-input>
- </el-form-item>
- <el-form-item label="密码" prop="password">
- <el-input
- type="password"
- v-model="loginForm.password"
- autocomplete="off"
- ></el-input>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="login('loginForm')">登录</el-button>
- <el-button @click="resetForm('loginForm')">重置</el-button>
- </el-form-item>
- </el-form>
- </el-card>
- </div>
- </template>
-
- <script>
- import { nameRule, passRule } from '../utils/validate.js'
- // import { setToken } from '@/utils/setToken.js'
- export default {
- data() {
- return {
- loginForm: {
- username: "",
- password: "",
- },
- rules: {
- username: [{ validator: nameRule, trigger: "blur" }],
- password: [{ validator: passRule, trigger: "blur" }],
- },
- };
- },
-
- methods: {
- login(loginForm) {
- this.$refs[loginForm].validate((valid) => {
- if (valid) {
- console.log(this.loginForm);
- this.service.post('/login',this.loginForm)
- .then((res) => {
- console.log(res.data)
- })
- } else {
- console.log(this.loginForm);
- }
- });
- },
- resetForm(loginForm) {
- this.$refs[loginForm].resetFields();
- },
- },
- };
- </script>
-
- <style lang="scss">
- .login {
- width: 100%;
- height: 100%;
- position: absolute;
- background: #88b2dc;
- .box-card {
- width: 450px;
- margin: 160px auto;
- .el-card__header {
- font-size: 34px;
- }
- .el-button {
- width: 30%;
- }
- }
- }
- </style>
ctrl+c关掉当前运行的项目,重新新建终端输入:npm run serve,修改了vue.config.js文件一定要重启项目,配置才会生效,再进行接口测试,否则会报错如下:访问的依旧是localhhost:8080端口
如果重启服务还是没有用,那就再一一排查一下语法,拼写是否有误或者漏掉,以下为我调试过程发现的:
axios封装分析(其实还可以更完善:axios发送的数据不能是对象,只能是字符串的形式,所以可以使用统一的工具类对axios发送请求的数据进行处理;以此类推,接收返回的请求,可以通过判断不同的状态码,进行不同的处理(500服务器内部错误、404访问地址不存在等)参考博文):
测试结果:
接下来是康康想一下,接口返回的数据,除了token还有什么是要存起来的===》username===》当登录成功,进入系统首页,需要显示用户名,所以:修改Login.vue页面的login方法为下:
- login(loginForm) {
- this.$refs[loginForm].validate((valid) => {
- if (valid) {
- console.log(this.loginForm);
- this.service.post('/login',this.loginForm)
- .then((res) => {
- if (res.data.status === 200) {
- setToken('username', res.data.username)
- setToken('token', res.data.token)
- this.$message({message: res.data.message, type: 'success'})
- this.$router.push('/home')
- }
- })
- } else {
- console.log(this.loginForm);
- }
- });
- },
做到这一步,发现代码没问题,但是为了方便后续项目整理和维护,管理接口和方法,∴把登录方法可以再封装成api进行调用:
在src下,新建api文件夹,新建api.js文件
- // 把对应的接口请求封装成api来调用
- import service from '../service.js'
-
- // 登录接口
- export function login(data) {
- return service({
- method: 'post',
- url: '/login',
- data
- })
- }
在Login.vue页面进行使用:
404页面
在项目中准备好静态资源:
在components下新建NotFound.vue
- <template>
- <div class="notfound">
- <div class="wrapper">
- <div class="big">页面不见了!</div>
- <div>首页瞧瞧,点击<router-link to="/">这里</router-link>进入首页.</div>
- </div>
- </div>
- </template>
-
- <script>
- export default {
- data() {
- return {};
- },
- };
- </script>
-
- <style>
- .notfound {
- height: 100%;
- background-image: url('../assets/img/astronauta.jpg'), url('../assets/img/stars404.png');
- background-position: right top, center center;
- background-repeat: no-repeat, repeat;
- background-size: cover, auto;
- }
- .notfound .wrapper {
- position: absolute;
- top: 60%;
- right: 2%;
- color: #fff;
- width: 635px;
- font-size: 19px;
- line-height: 29px;
- -webkit-font-smoothing: antialiased;
- padding: 20px;
- font-family: 'Source Sans Pro', sans-serif;
- }
- .notfound .wrapper .big {
- font-size: 74px;
- font-weight: 700;
- line-height: 68px;
- margin-bottom: 48px;
- }
- .notfound .wrapper a {
- color: #ffcc00;
- text-decoration: none;
- font-weight: 700;
- cursor: pointer;
- }
- @media only screen and (max-width: 666px) {
- .notfound .wrapper {
- left: auto;
- right: 0;
- width: 100%;
- max-width: 450px;
- top: 35%;
- }
- .notfound .wrapper .big {
- font-size: 42px;
- line-height: 50px;
- margin-bottom: 15px;
- }
- }
- </style>
配置路由
效果:
分析:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。