vue2后台管理(一)项目初始化+登陆界面+express的使用+axios封装使用

97 阅读4分钟

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的组件以及对应的引入。 image.png

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>

实现样式如下图

image.png

5.express的使用

express的使用,调用接口的时候,请在对应的文件夹通过node index.js启动

因为没有后端,所以我们使用express来模拟接口 在根目录下创建mock文件夹->创建index.js文件&&创建data文件夹

image.png

// 引入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")
})

image.png 在控制台输入node index.js,出现提示语,表示运行成功(需要注意的是mock文件夹中运行)

image.png 在网页中通过地址http://localhost:5500/login ,可以访问该接口,由于没有传值所以返回的是普通用户的数据

image.png 当我们传入get参数是admin时就会返回对应的admin数据 image.png

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>
...