B站云E办Vue+SpringBoot前后端分离项目——搭建vue.js项目(一)

项目前端学习笔记目录

B站云E办Vue+SpringBoot前后端分离项目——搭建vue.js项目

B站云E办Vue+SpringBoot前后端分离项目——前端动态获取菜单目录

项目后端学习笔记目录

B站云E办Vue+SpringBoot前后端分离项目——MVC三层架构搭建后台项目

项目简介

项目背景:受疫情的影响,许多企业由线上办公转为线下办公。随着线上办公的人数的增多,线上办公的优点逐步凸显:通过实现工作流程的自动化、节省企业办公费用、实现绿色办公,同时提升办公效率。

项目介绍:本项目实现了一个在线办公系统,用来管理日常办公事物的:日常流程审批,新闻,通知,公告,文件信息,财务,人事,费用,资产,行政,项目,移动办公等。通过软件的方式让办公系统根据方便管理,提高整体的管理运营水平。

实现方式:本项目基于Vue+Spring Boot构架一个前后端分离项目。前端使用社区非常活跃的开源框架vue进行构建。简单地说,前后端分离 的核心思想是前端页面通过 ajax 调用后端的 restuful api 进行数据交互,而 单页面应用(single page web application,SPA),就是只有一张页面,并在用户与应用程序交互时动态更新该页面的 Web 应用程序。

前后端之间通过 RESTful API 传递 JSON 数据进行交流。不同于 JSP 之类,后端是不涉及页面本身的内容的。在开发的时候,前端用前端的服务器(Nginx),后端用后端的服务器(Tomcat),当我开发前端内容的时候,可以把前端的请求通过前端服务器转发给后端(称为反向代理),这样就能实时观察结果,并且不需要知道后端怎么实现,而只需要知道接口提供的功能。

1.技术架构

B站云E办Vue+SpringBoot前后端分离项目——搭建vue.js项目(一)_第1张图片

 2.前端技术架构

B站云E办Vue+SpringBoot前后端分离项目——搭建vue.js项目(一)_第2张图片

本项目采用前后端分离开发模式,使用Spring Boot构建后端。前端模块分为:登录、职位管理、职称管理、部门管理、操作员历、员工管理、工资账套管理、个人中心、在线聊天

前端使用的技术有:

    项目搭建:Vue-cli

    状态管理:Vuex

    路由管理:VueRouter

    UI界面:ElementUI

    通讯框架:Axios

    前端语法:ES6

    打包:Webpack

    在线聊天:WebSocket

    字体:font-awesome

    文件上传下载:js-file-download

    在线聊天开源项目:vue-chat

3.后端技术架构

后端主流开发框架:SpringBoot+Spring MVC +MyBatisPlus。 使用SpringSecurity做安全认证及权限管理,Redis做缓存,RabbitMq做邮件的发送,使用EasyPOI实现对员工数据的导入和导出,使用WebSocket做在线聊天

B站云E办Vue+SpringBoot前后端分离项目——搭建vue.js项目(一)_第3张图片

    安全框架:SpringSecurity

    令牌:JWT

    图形验证码:Kaptcha

    缓存:redis

    文档导入导出:EasyPOI

    消息队列:RabbitMQ 做异步的处理,邮件发送

    邮件组件:Mail

    在线聊天:WebSocket

    文件服务器:FastDFS

    数据库MySQL+Redis

一、搭建vue.js项目

1.vue介绍

B站云E办Vue+SpringBoot前后端分离项目——搭建vue.js项目(一)_第4张图片

        原生JS虽能实现绝大部分功能,但要么就是过于繁琐,要么就是存在缺陷,故绝大多数开发者都会首选框架开发方案。 在框架方面,生命周期、钩子函数、虚拟DOM、Diff算法这些基本知识是必须要掌握的,其中不同级别组件间通信、组件状态管理、路由跳转、组件性能优化等等,都是应该达到灵活运用的程度。在前端项目开发中,我们可以根据实际情况不同程度地使用 Vue。利用 Vue CLI(或写成 vue-cli,即 Vue 脚手架)搭建出来的项目,是最能体现 Vue 的特性的。这点在接下来的内容中我们可以慢慢感受。

模块化开发就是将大的文件拆分为许多独立的小文件,按需在不同的组件中导入,降低了代码耦合度,提高了代码复用性。vue开发的是单页面应用,只有一个html入口,其余称为组件。真正的入口是main.js。vue:渐进式js框架,逐步实现新特性。如模块化开发、路由、状态管理等。

1.1 axios

前端通信框架。因为vue的边界很明确,就是为了处理DOM,所以不具备通信能力,此时就需要额外使用一个通信框架与服务器交互;当然也可以直接使用jQuery提供的AJAX通信功能。

1.2 Vue-router

Vue Router是Vue.js官方的路由管理器。它和Vue.js的核心深度集成,让构建单页面应用变得易如反掌。包含的 功能有:

嵌套的路由/视图表

模块化的、基于组件的路由配置

路由参数、查询、通配符

基于Vue.js过度系统的视图过渡效果

细粒度的导航控制

带有自动激活的CSS class的连接

HTML5历史模式或hash模式,在IE9中自动降级

自定义的滚动条行为

1.3 webpack

        前端开发和其他开发工作的主要区别,首先是前端基于多语言、多层次的编码和组织工作,其次前端产品的交付是基于浏览器的,这些资源是通过增量加载的方式运行到浏览器端,如何在开发环境组织好这些碎片化的代码和中资源,并且保证他们在浏览器快速、优雅的加载和更新,就需要一个模块化系统。

        webpack是一个现代javaScript应用程序静态模块打包器(module bundler)。当webpack处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle。webpack的思想:万物皆模块,即webpack不仅仅是javaScript模块化,还有CSS、图片、字体等资源也需要模块化。Webpack:模块打包器,主要作用是打包、压缩、合并及按序加载。如将ES6打包成ES5

        在webpack的配置文件里,设置了main.js是入口文件,我们的项目默认访问index.html,这个文件里面和App.vue组件里面的容器完美的重合了,也就是把组件挂载到了index页面,然后我们只需要去建设其他组件就好了,在App组件中我们也可以引入,注册,应用其他组件,可以通过路由将其他组件渲染在App组件,这样我们就只需要去关注每个组件的功能完善。就是说vue的默认页面是index.html,index中的挂载了App.vue这个大组件,然后所有的其他子组件(hello.vue等)都归属在App.vue这个主组件下。

1.4 ES6模块

        vue通常用es6来写,用export default导出,其下面可以包含数据data,生命周期(mounted等),方法(methods)等,具体语法请看vue.js文档。ES6标准增加了javascript语言层面的模块体系定义。ES6模块的设计思想,是尽量静态化,使编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS和AMD模块,都只能在运行时确定这些东西。

1.5 UI框架

Element-UI,饿了么出

1.6 vuex

专门为用程序开发的状态管理模式

npm install vuex --save

在src目录新建store目录,新建index.js文件,在main.js中引入

安装vuex 启动 报错 “export ‘watch‘ was not found in ‘vue‘

B站云E办Vue+SpringBoot前后端分离项目——搭建vue.js项目(一)_第5张图片

如果你的vue版本是 2.X ,将vuex升到 3.X.X 就能够解决

npm install --save [email protected]

如果你的vue版本是 3.X ,将vuex升到 4.X.X 就能够解决

npm install --save [email protected] npm install --save [email protected]

2.搭建vue.js项目

2.1环境准备

安装Node.js(>=6.x,首选8.x)本项目是v14.18.0版本

2.2安装 Vue CLI

因为需要使用 npm 安装 Vue CLI,而 npm 是集成在 Node.js 中的,所以第一步我们需要安装 Node.js,访问官网 Node.js,首页即可下载。

下载完成后运行安装包,一路下一步就行。

然后在 cmd 中输入 node -v,检查node是否安装成功。

输入 npm -v 查看npm版本号

输入 npm -g install npm ,将 npm 更新至最新版本。

之后,使用 npm install -g vue-cli 安装脚手架。(本项目使用版本2.9.6)

注意此种方式安装的是 2.x 版本的 Vue CLI,最新版本需要通过 npm install -g @vue/cli 安装。新版本可以使用图形化界面初始化项目,并加入了项目健康监控的内容,但使用新版本创建的项目依赖与这个教程不太相符,折腾起来比较麻烦。

安装Node.js的淘宝镜像加速器cnpm

大部分情况使用npm,遇到安装不了的使用cnpm

npm install cnpm -g

或npm install --registry=https://registry.npm.taobao.org

3.构建前端项目

通用方法直接使用命令行构建项目。

然后执行命令 vue init webpack yeb,这里 webpack 是以 webpack 为模板指生成项目,还可以替换为 pwa、simple 等参数,这里不再赘述。

在程序执行的过程中会有一些提示,可以按照默认的设定一路回车下去,也可以按需修改,比如下图问我项目名称是不是 wj-vue,直接回车确认就行。

这里还会问是否安装 vue-router,一定要选是,也就是回车或按 Y,vue-router 是我们构建单页面应用的关键。

还有是否使用 es-lint,选N。

接下来等待项目构建完成就 OK 了。

workspace 目录下生成了项目文件夹 需要在该文件夹执行 npm install ,npm run build 再执行 npm run dev

访问 http://localhost:8080,查看网页 demo,大工告成!

注:在vue项目中,有的时候需要执行npm run serve启动项目,有的时候需要用npm run dev,具体有什么不一样呢?

区别

dev默认是[email protected]默认支持的命令;

serve默认是[email protected]及以上版本默认支持的命令。

4.vue项目结构分析

B站云E办Vue+SpringBoot前后端分离项目——搭建vue.js项目(一)_第6张图片

├── build --------------------------------- 项目构建(webpack)相关配置文件,配置参数什么的,一般不用动

│ ├── build.js --------------------------webpack打包配置文件

│ ├── check-versions.js ------------------------------ 检查npm,nodejs版本

│ ├── dev-client.js ---------------------------------- 设置环境

│ ├── dev-server.js ---------------------------------- 创建express服务器,配置中间件,启动可热重载的服务器,用于开发项目

│ ├── utils.js --------------------------------------- 配置资源路径,配置css加载器

│ ├── vue-loader.conf.js ----------------------------- 配置css加载器等

│ ├── webpack.base.conf.js --------------------------- webpack基本配置

│ ├── webpack.dev.conf.js ---------------------------- 用于开发的webpack设置

│ ├── webpack.prod.conf.js --------------------------- 用于打包的webpack设置

├── config ---------------------------------- 配置目录,包括端口号等。我们初学可以使用默认的。

│ ├── dev.env.js -------------------------- 开发环境变量

│ ├── index.js ---------------------------- 项目配置文件

│ ├── prod.env.js ------------------------- 生产环境变量

│ ├── test.env.js ------------------------- 测试环境变量

├── node_modules ---------------------------- npm 加载的项目依赖模块

├── src ------------------------------------- 我们要开发的目录,基本上要做的事情都在这个目录里。

│ ├── assets ------------------------------ 静态文件,放置一些图片,如logo等

│ ├── components -------------------------- 组件目录,存放组件文件,可以不用。

│ ├── main.js ----------------------------- 主js

│ ├── App.vue ----------------------------- 项目入口组件,我们也可以直接将组件写这里,而不使用 components 目录。

│ ├── router ------------------------------ 路由

├── static ---------------------------- 静态资源目录,如图片、字体等。

├── .babelrc--------------------------------- babel配置文件

├── .editorconfig---------------------------- 编辑器配置

├── .gitignore------------------------------- 配置git可忽略的文件

├── index.html ------------------------------ 首页入口文件,你可以添加一些 meta 信息或统计代码啥的。

├── package.json ---------------------------- node配置文件,记载着一些命令和依赖还有简要的项目描述信息

├── .README.md------------------------------- 项目的说明文档,markdown 格式。想怎么写怎么写,不会写就参照github上star多的项目,看人家怎么写的

主要文件详解

4.1 src——[项目核心文件]

在vue-cli的项目中,其中src文件夹是必须要掌握的,因为基本上要做的事情都在这个目录里。

4.2 index.html——[主页]

index.html如其他html一样,但一般只定义一个空的根节点,在main.js里面定义的实例将挂载在根节点下,内容都通过vue组件来填充,构建的文件将会被自动注入,也就是说我们编写的其它的内容都将在这个 div 中展示。整个项目只有这一个 html 文件,所以这是一个 单页面应用,当我们打开这个应用,表面上可以有很多页面,实际上它们都只不过在一个 div 中。



  
    
    vuedemo
  
  
      
    

4.3 App.vue——[根组件]

这个文件称为“根组件”,因为其它的组件又都包含在这个组件中。.vue 文件是一种自定义文件类型,在结构上类似 html,一个 .vue 文件即是一个 vue 组件。

一个vue页面通常由三部分组成:模板(template)、js(script)、样式(style)








【template】

其中模板只能包含一个父节点,也就是说顶层的div只能有一个(例如上面代码,父节点为#app的div,其没有兄弟节点)。这里也有一句

,但跟 index.html 里的那个是没有关系的。这个id=app 只是跟下面的 css 对应。
是子路由视图,后面的路由页面都显示在此处。打一个比喻吧,类似于一个插槽,跳转某个路由时,该路由下的页面就插在这个插槽中渲染显示

【script】

 SessionStorage.setItem()中,为了使axios做下一次请求时获取token认证,登录之后拿到token放到sessionStrorage里         

    // 存储用户 token 到 sessionStorage

                const tokenStr = resp.obj.tokenHead + resp.obj.token;

                window.sessionStorage.setItem('tokenStr', tokenStr);

3.配置页面路由——router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import Login from "@/views/Login";

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Login',
      component: Login,
      hidden: true // 不会被循环遍历出来
  },
  ]
})

4.解决前后端跨域

前端端口默认8080,假设后端端口是8081,那8080如何访问到8081的数据,我们通过Node.js实现端口自动转发。浏览器的同源策略:两个页面必须具有相同的协议(protocol)主机(host)端口号(port)。

请求一个接口时,出现Access-Control-Allow-Origin等,说明出现请求跨域了。vue中解决跨域的方法:配置vue.config.js文件,如果没有就自行新建一个。

原理:

1.将域名发送给本地的服务器(localhost:8080)

2.再由本地的服务器去请求真正的服务器

3.因为请求是从服务端发出的,所以不存在跨域的问题了。

在vue中是由node.js自动进行的

4.1前端反向代理

修改main.js

修改 src\main.js 代码如下:

import Vue from 'vue'
import App from './App'
import router from './router'
// 设置反向代理,前端请求默认发送到 http://localhost:8081/api
var axios = require('axios')
axios.defaults.baseURL = 'http://localhost:8081/api'
// 全局注册,之后可在其他组件中通过 this.$axios 发送数据
Vue.prototype.$axios = axios
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: ''
})

修改vue.config.js 

修改proxyTable 请求地址经过node.js后代理到后端地址8081


    proxyTable: {
      '/': {
        changeOrigin: true, //跨域
        target: 'http://localhost:8081',
        pathRewrite: {
          // '^/api': ''
        }
      },
    
    },

5.登陆拦截器

拦截器顾名思义就是对请求的拦截,分别为请求拦截器和响应拦截器, 执行顺序: 请求拦截器 -> api请求 -> 响应拦截器。 拦截器的作用:a. 统计api从发起请求到返回数据需要的时间;b. 配置公共的请求头,加载弹窗等;c. 对响应状态码做拦截,比入后端返回400或500的状态码, 返回对应错误信息。

5.1axios请求拦截器request

在vue项目中,我们通常使用axios与后台进行数据交互,axios是一款基于promise封装的库,可以运行在浏览器端和node环境中。请求拦截器request作用:在请求发送前统一执行某些操作,常用在请求头中处理token等 

添加请求拦截器的方法

axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
})

5.2axios响应拦截器response

返回对象response中有response.status:Http响应码;response.data:后端返回的Json对象,包括response.data.code业务逻辑响应码,response.data.message:后端返回的响应提示信息;

添加响应拦截器方法

axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
}

5.3封装请求

在项目中,我们并不会直接使用 axios,而是会对它进行一层封装。 通过export导出封装的请求,如定义一个postRequest方法接收url和params,然后axios对象。在axios里进行实际接口调用操作。

export const postRequest = (url, params) => {
    return axios({
        method: 'post',
        url: `${base}${url}`,
        data: params
    })
}

 5.4代码实现src/utils/api.js

import axios from "axios";
import {Message} from "element-ui";
import router from "@/router";

// 请求拦截器
axios.interceptors.request.use(config => {
    // 如果存在 token,请求携带这个 token( 登录的时候 把 token 存入了 sessionStorage )
    if (window.sessionStorage.getItem("tokenStr")) {
        // token 的key : Authorization ; value: tokenStr
        config.headers['Authorization'] = window.sessionStorage.getItem('tokenStr')
    }
    return config;
},error => {
    console.log(error)
})

// 响应拦截器 - 统一处理消息提示
axios.interceptors.response.use(success => {
    // 业务逻辑错误
    if (success.status && success.status === 200) { // 调到接口
        // 后端:500 业务逻辑错误,401 未登录,403 无权访问;
        if (success.data.code === 500 || success.data.code === 401 || success.data.code === 403) {
            Message.error({message: success.data.message})
            return
        }
        if (success.data.message) { // 输出后端 添加成功 之类的信息
            Message.success({message: success.data.message})
        }
    }
    return success.data
}, error => { // 没访问到后端接口
    if (error.response.code === 504 || error.response.code === 404) {
        Message.error({message: '服务器不存在'})
    } else if (error.response.code === 403) {
        Message.error({message: '权限不足,请联系管理员!'})
    } else if (error.response.code === 401) {
        Message.error({message: '您还未登录,请登录!'})
        router.replace('/') // 路由替换
    } else {
        if (error.response.data.message) {
            Message.error({message: error.response.data.message})
        } else {
            Message.error({message: '未知错误!'})
        }
    }
    return
})

// 预备前置路径
let base = '';

// 传送 json 格式的 post 请求
export const postRequest = (url, params) => {
    return axios({
        method: 'post',
        url: `${base}${url}`,
        data: params
    })
}

// 传送 json 格式的 get 请求
export const getRequest = (url, params) => {
    return axios({
        method: 'get',
        url: `${base}${url}`,
        data: params
    })
}

// 传送 json 格式的 put 请求
export const putRequest = (url, params) => {
    return axios({
        method: 'put',
        url: `${base}${url}`,
        data: params
    })
}

// 传送 json 格式的 delete 请求
export const deleteRequest = (url, params) => {
    return axios({
        method: 'delete',
        url: `${base}${url}`,
        data: params
    })
}

5.5main.js全局引入封装请求

通过main.js全局引入然后通过插件的方式使用方法。在具体调用时使用this.putRequest(url,params)形式使用

import {postRequest} from "@/utils/api";
import {putRequest} from "@/utils/api";
import {getRequest} from "@/utils/api";
import {deleteRequest} from "@/utils/api";
Vue.prototype.postRequest = postRequest
Vue.prototype.putRequest = putRequest
Vue.prototype.getRequest = getRequest
Vue.prototype.deleteRequest = deleteRequest

6. 前端路由导航守卫

登录页面的开发似乎已经较为完善了,但其实还没有完,因为这个登录页面其实没有用,别人直接输入首页的网址,就可以绕过登录页面。为了让它发挥作用,我们还需要开发一个拦截器。使用钩子函数判断是否拦截函数及在某些时机会被调用的函数。这里我们使用 router.beforeEach(),意思是在访问每一个路由前调用。to 要去的路由; from 来自哪里的路由 ; next() 放行。

通过sessionStorage.getItem('user')获取用户的token,如果token不存在则需要登陆。

在判断是否为if (to.path == '/')登陆页,是的话放行,否则按用户指定的路由登陆;

补充main.js

// 使用 router.beforeEach 注册一个全局前置守卫
router.beforeEach((to, from, next) => {
  // to 要去的路由; from 来自哪里的路由 ; next() 放行
  // 用户登录成功时,把 token 存入 sessionStorage,如果携带 token,初始化菜单,放行
  if (window.sessionStorage.getItem('tokenStr')) {
      // 如果用户不存在
         //待首页功能部分完善后补充
  } else {
      if (to.path === '/') {
          next()
      } else {
          next('/?redirect=' + to.path)
      }
  }
})

7.运行项目

B站云E办Vue+SpringBoot前后端分离项目——搭建vue.js项目(一)_第11张图片

下一篇

B站云E办Vue+SpringBoot前后端分离项目——前端动态获取菜单目录

你可能感兴趣的:(前端,vue.js,spring,boot)