1.项目初始化,安装所需要的依赖
1.创建项目并引入所需的一些依赖
2.element.ui的按需引入(按需引入的好处是打包的时候文件会小,一些不使用的组件就不会被引入)
// 创建项目
vue create vue2-project
// 安装依赖
// 安装axios发送ajax
cnpm install axios --save
// 安装vue-router 注意版本
npm install --legacy-peer-deps vue-router@3.2.0
// 按需引入element-ui(分清vue2和vue3)
npm i element-ui -S
// 先安装babel-plugin-component
npm install babel-plugin-component -D
// 安装指定版本的less
npm install less-loader@7.0.0
npm install less --save-dev
修改babel.config.js
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk'
}
]
]
}
在main.js中引入elementUI,按需引入。每当使用组件时都需要引入之后再进行使用。
import Vue from 'vue'
import App from './App.vue'
import { Button, Select } from 'element-ui';
Vue.config.productionTip = false
Vue.use(Button);
Vue.use(Select);
new Vue({
render: h => h(App),
}).$mount('#app')
删掉helloWorld的组件以及对应的引入。
npm install
// 启动项目
npm run serve
2.创建路由
重点:router.beforeEach路由守卫的实现,
to:将要去的页面 from:将要离开的页面 next()下一步,如果没有就不会进行跳转
创建views文件夹->创建login文件夹->创建login-index.vue文件
在src目录下创建router->创建index.js文件用来生成路由
import Vue from 'vue'
import Router from "vue-router"
import Login from "./views/login/login-index.vue"
Vue.use(Router)
// constantRoutes静态路由,主要是登录页、404页等不需要动态的路由
export const constantRoutes = [
{
path: '/',
name: '',
hidden: true,
redirect: '/login', //重定向
},
{
path: '/login',
name: "登陆",
component:Login
}
]
const createRouter = () => new Router({
/**
在列表页切换路由的时候,滚动条会停留在上一个页面滚动条滚动的位置,scrollBehavior设置{y:0}可以
对于所有路由导航,简单地让页面滚动到顶部。
*/
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
const router = createRouter()
// 路由守卫
router.beforeEach((to,from,next) => {
if(to.path === "/login" || to.path === "/") return next();
// 获取sessionStorage中的token
const tokenStr = window.sessionStorage.getItem("token");
if(!tokenStr) {
return next("/login")
}else {
return next()
}
})
export default router;
在main.js文件中引入router.js,并且先对login页面的一些elementui组件进行按需引入
import Vue from 'vue'
import App from './App.vue'
import router from "./router/index"
import { Button, Select, Form, FormItem, Input, Message } from 'element-ui';
Vue.config.productionTip = false
Vue.use(Button);
Vue.use(Select);
Vue.use(Form);
Vue.use(FormItem);
Vue.use(Input);
Vue.prototype.$message = Message
new Vue({
router,
render: h => h(App),
}).$mount('#app')
3.设置全局样式表
在assets文件夹中创建css文件夹->创建global.css文件
/* 全局样式表 */
html,body,#app{
width: 100%;
height: 100%;
padding: 0;
margin:0;
}
并在main.js中引入
// 引入全局样式
import './assets/css/global.css'
4.登陆界面的实现
1.按需引入需要注意,使用未引入的组件需提前引入
2.el-from的使用,比如rules,表单的判断以及重置等
需要注意的是elementUI我们采用的是按需引入,所以需要在main.js文件中引入,在前面我们有提前引入,之后要是遇到报错,可以查找是否因为这个组件没有引入导致的。
// 使用router-view占位符,这样才能显示我们通过router引入的页面
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
name: "App",
};
</script>
<style></style>
<template>
<div class="login_container">
<div class="login_box">
<!-- 头像区域 -->
<div class="avatar_box">
<img src="@/assets/logo.png" alt="" />
</div>
<!-- 表单区域 -->
<el-form
label-position="left"
ref="loginFrom"
:model="loginForm"
:rules="loginFormRules"
class="login_form"
>
<el-form-item prop="userName">
<el-input
prefix-icon="el-icon-user"
v-model="loginForm.userName"
></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
prefix-icon="el-icon-lock"
show-password
v-model="loginForm.password"
></el-input>
</el-form-item>
<el-form-item class="btn">
<el-button type="primary" @click="login()">登录</el-button>
<el-button type="info" @click="resetLoginForm()">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
export default {
name: "LoginIndex",
data() {
return {
loginForm: {
userName: "admin",
password: "123456",
},
loginFormRules: {
userName: [
{ required: true, message: "请输入用户名", trigger: "blur" },
{
min: 3,
max: 10,
message: "长度在 3 到 10 个字符",
trigger: "blur",
},
],
password: [
{ required: true, message: "请输入密码", trigger: "blur" },
{
min: 5,
max: 20,
message: "长度在 5 到 20 个字符",
trigger: "blur",
},
],
},
};
},
methods: {
login() {
this.$refs.loginFrom.validate((valid) => {
if (valid) {
this.$message.success("登陆成功");
} else {
console.log("error submit!!");
return false;
}
});
},
resetLoginForm() {
this.$refs.loginFrom.resetFields();
},
},
};
</script>
<style lang="less" scoped>
.login_container {
background: #2b4b6b;
width: 100%;
height: 100%;
}
.login_box {
width: 450px;
height: 300px;
background-color: #fff;
border-radius: 3px;
// 如何让盒子垂直居中
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
.avatar_box {
width: 130px;
height: 130px;
border: 1px solid #eee;
border-radius: 50%;
padding: 10px;
box-shadow: 0 0 10px #ddd;
position: absolute;
// 盒子总长度为130+10+10+2
left: calc(50% - 76px);
top: -76px;
background: #fff;
img {
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #eee;
}
}
.login_form {
position: absolute;
width: calc(100% - 40px);
bottom: 0;
padding: 0 20px;
}
.btn {
display: flex;
justify-content: flex-end;
}
}
</style>
实现样式如下图
5.express的使用
express的使用,调用接口的时候,请在对应的文件夹通过node index.js启动
因为没有后端,所以我们使用express来模拟接口 在根目录下创建mock文件夹->创建index.js文件&&创建data文件夹
// 引入express
npm install --save express
在data文件夹中创建admin_login.json和user_login.json user_login.json和amdin_login.json数据差不多仅仅token不同用于区分
{
"code": 200,
"message": "登陆成功",
"data":{
"token":"admin"
}
}
在index.js文件中使用express
const express = require("express");
const app = express();
const adminLogin = require("./data/admin_login.json");
const userLogin = require("./data/user_login.json");
const url = require("url");
app.get("/login",(req,res) => {
const user = url.parse(req.url,true).query.user;
if(user === "admin"){
res.send(adminLogin);
}else {
res.send(userLogin);
}
})
app.listen(5500,()=>{
console.log("服务器运行在5500")
})
在控制台输入node index.js,出现提示语,表示运行成功(需要注意的是mock文件夹中运行)
在网页中通过地址http://localhost:5500/login ,可以访问该接口,由于没有传值所以返回的是普通用户的数据
当我们传入get参数是admin时就会返回对应的admin数据
6.vue.config.js文件的配置
跨域问题的解决以及@指向src,避免路径出错
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
devServer: {
proxy:{
'/api':{
target:'http://localhost:3300',
changeOrigin: true,
pathRewrite:{
'^/api': ''
}
}
}
},
lintOnSave:false,// 关闭Eslint语法检查
// @指向src路径
configureWebpack: {
resolve: {
alias: {
'@': resolve('src'),
}
}
},
}
7.axios的封装和对调用api的二次封装以及调用实现登陆功能
1.axios的封装,封装了请求拦截器和相应拦截器
2.对接口进一步进行封装,以及对封装好的接口进行调用
跳转页面的时候进行拦截,判断跳转的页面是否为login,只有login页面可以直接访问不需要判断权限
若不是/login跳转,就需要判断token是否存在,不存在就需要强制跳转login页面,用来重新获取token
如果token存在就跳转将要访问的页面
这里的知识点就是router.berforeEach的使用,有三个参数分别是to,from,next。
to:即将访问的页面
from:即将离开的页面
next():下一步的操作,若不传值就是跳转到访问的页面,若是传值,就跳转传入的页面。
src目录下创建utils文件夹->创建require.js文件 这里我们对aixos进行了封装,增加请求响应拦截器
import axios from "axios";
const request = axios.create({
// baseURL: "http://localhost:3300",
timeout: 5000, //设置接口的超时时间
headers: {
"Content-Type": "application/json",
},
});
// 添加请求拦截器
request.interceptors.request.use(config => {
// 发送请求前我们需要做什么
// 每次请求发送前都需要加上我们的token,用来判断用户的身份
config.headers.Authorization = window.sessionStorage.getItem("token")
// 最后必须返回这个config
return config
},err=>{
console.log(error)
return Promise.reject(error);
});
//响应拦截器
request.interceptors.response.use(response => {
//请求成功后,对服务器返回的数据进行的统一操作。
//判断状态码
const res = response.data;
if (res.code && res.code !== 200) {
// 登录超时,重新登录
if (res.code === 401) {
this.$message.error("登陆超时");
}
return Promise.reject(res || 'error')
} else {
return res.data
}
})
export default request;
src目录下创建api文件夹->创建base.js文件 封装login接口
import request from '@/utils/require';
// 登陆接口(get方式)
export function login(user) {
return request.get("/api/login?user=" + user);
}
在login-index.vue中调用login接口
...
<script>
import { login } from "@/api/base";
export default {
name: "LoginIndex",
data() {
return {
loginForm: {
userName: "admin",
password: "123456",
},
loginFormRules: {
userName: [
{ required: true, message: "请输入用户名", trigger: "blur" },
{
min: 3,
max: 10,
message: "长度在 3 到 10 个字符",
trigger: "blur",
},
],
password: [
{ required: true, message: "请输入密码", trigger: "blur" },
{
min: 5,
max: 20,
message: "长度在 5 到 20 个字符",
trigger: "blur",
},
],
},
};
},
methods: {
async login() {
this.$refs.loginFrom.validate(async (valid) => {
if (valid) {
await login(this.loginForm.userName)
.then((res) => {
if (res) {
console.log(res);
let token = res.token;
console.log("登陆成功获取到的token值为:" + token);
window.sessionStorage.setItem("token", token);
window.sessionStorage.setItem(
"userName",
this.loginForm.userName
);
this.$message.success("登陆成功");
this.$router.push("/home");
// 1.登陆成功之后的token,保存在sessionStorage中
// 1.1.项目中的其他页面以及接口,必须登陆成功之后才能被访问
// 1.2 token只应在当前网站打开期间生效,所以将token存放在sessionStorage中
// 也可以存在在localStorage中,设置token的失效时间,若失效,就需要重新登陆
// 2.登陆成功后生成对应的权限的路由地址,以及导航到首页中/home。
} else {
this.$message.error("用户名密码错误请重新输入");
this.$refs.loginFrom.resetFields();
}
})
.catch((err) => {
console.log(err);
});
} else {
console.log("error submit!!");
return false;
}
});
},
resetLoginForm() {
this.$refs.loginFrom.resetFields();
},
},
};
</script>
...