基于Vue的前后端分离项目实践
一、为什么需要前后端分离
1.1什么是前后端分离
前后端分离这个词刚在毕业(15年)那会就听说过,但是直到17年前都没有接触过前后端分离的项目。怎么理解前后端分离?直观的感觉就是前后端分开去做,即功能和职责上的一种划分,前端负责页面的渲染,部分页面交互的逻辑,然后通过网络请求与后端进行数据的交互;后端则着重关注业务逻辑的处理,直接操控数据库。
1.2前后端未分离前
(1)jsp + servlet 开发模式:
jsp页面:负责视图层的渲染及交互,内部可以嵌入java 代码,在某些场景下开发起来比较方便,但是这种页面和java代码混合开发的方式造成逻辑不够直观,项目代码维护起来困难。
servlet类: 负责接收from表单提交的参数,进行业务层逻辑和页面导航的处理。但是这种方式需要区分请求的方式,手动把请求的参数拿出来进行封装。基本上一个请求对应一个servlet,需要在web.xml文件中配置url映射或者注解的方式。
大体流程:
编写jsp页面,引入java常用类库和jstl标签库,编写html表单,css,javascript。
编写servlet 方法,重写service()方法,需要手动获取请求参数,然后业务逻辑处理。
配置web.xml。在web.xml文件中注册servlet,配置请求映射(简单方法:增加注册)。
(2)jsp + spring mvc开发模式:spring 框架流行起来后,着重关注的是分层设计,即mvc的概念,个人认为jsp+spring 带来的最大好处是简化了之前servlet时代编写web流程的复杂度,各种注解、各种参数自动注入极大提高了java web的开发效率,此时对jsp页面有一个共同的约束,即jsp页面不要在嵌入除标签外的java代码,这样初步把视图层抽出来。但是这种方式的约束性依然很大,即应用强依赖于java生态。
大体流程:
搭建spring 框架,在web.xml中配置spring mvc的分发器。
编写jsp页面,利用各种jquery插件和前端css框架,也能做出漂亮的交互界面。
编写spring controller,只需要几个注解即可和表单的请求匹配,web请求的参数能够自动注入到controller请求的方法,一个controller可以匹配n多个请求。其中controller可以分为两种,一种是返回页面路径的controller,这个controller可以携带java对象到页面;另外一种是返回特定格式的json,常用的是json.
(3)模板+spring boot:
spring boot是spirng的一个脚手架,能够快速搭建spring项目,使用默认配置减少开发者手动的配置,与第三发包的各种整。模板相对于jsp页面来说,进一步进行视图层的模块化,即可以按照页面的结构进行划分,常用的例如header,footer,silder menu, center conter这样的版块接口进行划分,把页面进行分片处理,提高代码的复用度。
模块划分如下:
1.3前后端分离后
从上面可以看到java web生态系统不断的完善和加强,对于绝大多少web系统的开发来说足够了,那为什么要搞前后端分离?个人认为有以下几个原因:一个是职责划分需要,页面开发和业务逻辑开发并行进行来缩短开发周期。二是术业有专攻,随着页面的交互、ui要求不断提升,前端同学在页面方面的开发更具有专业性。三是前端具有强大的生态系统,有许多现成的组件和框架可以进行大项目的模块化开发,正则意义上实现交互和逻辑的逻辑和物理上的完全分离。
前端项目+后台接口
1.4前后端分离的优点与缺点
优点:
对于中大型项目,能够提升开发效率,提高交互和ui效果,缩短开发周期。
前端能够处理一大部分验证和交互逻辑,从而减少与服务器间的交互次数,减小服务器处理压力,并且页面是由浏览器渲染生成。
前端具有强大的组件库和处理工具,项目更容易跨平台。
降低维护成本。
接口和前端组件能够复用。
缺点:
需要更多的沟通成本。未进行前后端分离时,由后端同学完成整个项目的开发,前后端分离时需要和前端同学进行接口的沟通和联调。
对于小、交互性要求不高的项目,进行前后端分离反而效率较低,当然全栈开发除外。
部署流程更复杂。前后端分离一般是两个项目环境,需要投入更多硬件和运维。
二、前后端分离步骤
2.1 分离前的业务功能划分
职责划分:当从非前后端分离的项目转到前后端分离的项目,如何确认分离的切入点?首选需要理解前后端的职责,即前端负责页面构建和交互处理,后端负责接口定义和业务处理。所有页面上能看到的功能基本都是前端的,所有涉及数据的查询、保存都是后端的,前端不需要关心数据的输入和输出,而关注数据在这个过程中的交互逻辑;后端需要关心页面如何渲染和交互,而关注输出数据和接收数据。从上面可以看出职责即是功能的划分。
模块划分:前后端模块划分关注点不同。后端模块划分时一般有两种方式,第一种是先分层,再按照模块划分。即先按照全局、工具、控制层、服务层、数据操作层等这种基于mvc的结构进行划分,然后再将控制层、服务层、数据操作层按照业务模块进行划分。第二种方式按先模块后结构进行划分,即先按照业务模块划分不同的结构,然后每个模块根据需要决定是否进行mvc结构的划分。第一种更适用于中小型项目的构建,第二种更适用于大型项目,能够对按照业务垂直划分结构,方便部署和扩展。
前端模块划分基本基于功能的层次结构。第一层一般是全局配置、静态资源、工具类、视图、组件并列的结构,第二层是组件的复合结构和视图的复合结构,第三层是组件的独立结构。
2.2 前端需要了解的知识点
在进行前后端分离之前需要普及一下前端相关的知识。如下:
javascript:
基本概念:javascript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为javascript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在html(标准通用标记语言下的一个应用)网页上使用,用来给html网页增加动态功能。它由ecmascript(描述该语言的语法和基本对象)、文档对象模型(dom,描述处理网页内容的方法和接口)、浏览器对象模型(bom,描述与浏览器进行交互的方法和接口)三部分构成。
生态:这里说的生态即简单介绍一下js能够做些什么。数据可视化,例如d3.js、百度的echars;移动端应用,例如cordova、deviceone,能够一次开发多平台发布。服务端:node.js,常用的框架有express;桌面应用:nw.js和electron,他们可以使用html和javascript开发桌面一个应用,而且一次开发,多平台运行。其它的还有游戏(webgl)、ar、vr的应用支持。
mvvm:mvvm是model-view-viewmodel的缩写。这个可以和mvc进行对比一下。mvc如下:
mvvm如下:
这里可以看到相对于mvc,mvvm多了一个viewmodel的概念。在前端页面中,把model用纯javascript对象表示,view 负责显示,两者做到了最大限度的分离。把model和view关联起来就是viewmodel。viewmodel负责吧model的数据同步到view显示出来,还负责把view的修改同步到model。想象一下传统的mvc开发web应用的流程?
vue: vue 是一个mvvm的渐进式框架,被设计可以自定向上逐层应用。vue核心库只关注视图层,不仅易于上手,还便于与第三方库或已有项目整合。
node: node.js 是一个基于 chrome v8 引擎的 javascript 运行环境。node.js 使用了一个事件驱动、非阻塞式 i/o 的模型,使其轻量又高效。node.js 的包管理器 npm,是全球最大的开源库生态系统。
es6: es6的全名是ecmascript 2015。ecmascript 6.0(以下简称 es6)是 javascript 语言的下一代标准,已经在2015年6月正式发布了。它的目标,是使得 javascript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
node express 框架: express 是一个简洁而灵活的 node.js web应用框架, 提供了一系列强大特性帮助你创建各种 web 应用,和丰富的 http 工具。使用 express 可以快速地搭建一个完整功能的网站。express 框架核心特性:(1)可以设置中间件来响应 http 请求。(2)定义了路由表用于执行不同的 http 请求动作。(3)可以通过向模板传递参数来动态渲染 html 页面。
iview: iview 是一个基于vue 的第三方组件库,包含了后台开发过程中最基本的组件,组件代码比较简洁,文档和示例比较全。
iview admin: 一个github开源项目,是基于iview 基础组件构建的一个后台管理系统,包含了最基本的路由、状态管理、权限等后台系统共有的功能,可基于此系统进行后台的订制开发。
2.3 前后端分离项目开发流程
前后端分离的项目开发过程中最重要的就是接口文档的编写,它是前后端交互的门户。
2.4 前端开发方法
了解脚手架(cli):脚手架的意思是帮你快速开始一个vue的项目,也就是给你一套vue的结构,包含基础的依赖库,只需要 npm install就可以安装,让我们不需要为了编辑或者一些其他事情浪费时间 总而言之,就是快速搭建项目的,让我们可以早点去写代码。vue 官网提供了相应的cli工具,帮助我们快速搭建项目。
了解构建工具:这里介绍一下webpack。前端项目开发是使用vue基于组件方式进行的,但是运行时需要生成浏览器可以理解的js、css、html文件,那这两中文件形式的转换就是webpack的作用,它打包所有资源、打包所有脚本、打包所有图片、打包所有样式。
基本插件:babel: 他是一种用途很多的javascript编译器,他把最新版的javascript编译成当下可以执行的版本,简言之,利用babel就可以让我们在当前的项目中随意的使用这些新最新的es6,甚至es7的语法。eslint: eslint 是一个语法规则和代码风格的检查工具,可以用来保证写出语法正确、风格统一的代码。
组件设计:
什么是组件?从代码层面来说一个.vue文件就是一个组件,从功能层面来说组件应该是一个可以复用的功能。组件的特点是当一个组件设计完毕后,后续需要类似的功能,只需要简单的引用组件,然后做些定制化的配置即可。个人理解组件可以划分两大类,第一类是基础组件/原子组件,这类组件是页面的基础构成不封,本身不可或者不宜再划分为子组件,例如button,table,这类都算是基础组件,iview基本上是一个基础组件库。第二类是复合组件/框架性组件,这类组件是由基本组件经过合理的布局聚合在一起构成的,它拥有许多默认的配置,从而在类似的页面视图页面能够极大的减小重复代码。
设计原则:(1)基本思想是组件应该是于业务无关的。设计组件时不应该有任何具体业务逻辑因素的影响。(2)组件时复用代码和视图的抽象,多关注不同的页面,找出共同的接口和不同的特效,抽象出公用的部分。(3)组件应该足够灵活,后续功能特效的新增,不应该对原有引用组件的地方构成影响。
实例分析(复合组件):
2.5 前后端交互
保证前后端开发功能的正确性除了详细的需求文档和原型设计外,重要的就是接口文档。接口文档描述了前后端数据交互的方法、格式。前后端项目分离后,许多之前后端需要处理的工作,都将由前端处理,主要涉及以下:页面的导航功能,即vue router、组件之间公共信息的保存,即vuex,服务器数据资源的请求,即axios,其它的比较主要的就是权限、安全。
路由:vue router 是 vue.js 官方的路由管理器。它和 vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:(1)嵌套的路由/视图表;
(2)模块化的、基于组件的路由配置;(3)路由参数、查询、通配符;(4)基于 vue.js 过渡系统的视图过渡效果;(5)细粒度的导航控制;(6)带有自动激活的 css class 的链接
状态:vuex是一个专为vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.多个视图依赖于同一状态。为什么需要它?在开发应用中组件之间需要进行信息交流,父组件通过props属性注入数据,子组件通过感受数据的变化进行相应的逻辑相应。子组件通过自定义事件的方式告知父组件数据发生变化。但是这两种方式只合适对于嵌套层次不深的组件,并且对于兄弟组件间的状态传递无能为力。因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
资源:这里所说的资源主要是指数据资源,即决定前端是否有权限去访问数据资源,一般采用携带token的方式保证资源的安全性。后端采用自定义token策略或者标准的oauth 认证策略。
权限:前后端分离后,后端主要控制资源的权限,前端控制页面的权限。权限控制可以分为两大类,第一类是视图权限,即不同的用户只能看到自己改看到的东西,这个细分为菜单权限和按钮权限,菜单权限限制了用户看到的页面;按钮权限限制了用户在页面能够进行的操作。第二类是资源权限:即用户是否用访问数据资源的权限,这类权限在后台项目中不常见。
菜单权限的实现方法:第一种由前端维护菜单权限,即前端拥有所有的菜单映射,当用户登录后,根据用户的角色对菜单权限进行刷选,类似数据库表和视图的关系,这种方式开发成本较低,能够满足绝大多数对权限变动频率低的系统,缺点是有一定的维护成本,功能不够灵活。第二种是由后端决定菜单权限,即用户登录成功后,菜单树由后端生成直接返回,这样做是足够灵活,但是开发、沟通需要付出更多的时间。第三种是混合开发:即静态权限和动态权限相结合。很多后台系统有一部分菜单是角色公共的后者基本固定角色的,这部分菜单应该由前端预选定义好,对于变动较多的菜单,由后端返回必要信息,进行简单拼接即可。这种方式的工作量介于第一种和第二种之间。
按钮权限:按钮权限一般通过自定义指令实现,即自定义vue权限指令,根据传入的角色决定按钮是否显示。但是这种只适用于页面有表单组件的页面,对于需要动态生成的组件页面,需要提供一个全局权限查询方法。
2.5 前端项目部署
部署方式:前后端分离的项目一般有两种部署方式。第一种是通过build命令将项目打包成静态资源,然后copy静态资源到后端项目的静态目前下,然后通过tomcat服务器进行启动即可,这种方式不推荐。第二种方式是前后端分别部署,前端项目可以使用node 启动一个服务,运行在node环境中,后端部署在tomcat中,这种方式方便前后端各自水平扩展。
推荐阅读
-
从零开始搭建前后端分离的NetCore2.2(EF Core CodeFirst+Autofac)+Vue的项目框架之七使用JWT生成Token(个人见解)
-
从零开始搭建前后端分离的NetCore2.2(EF Core CodeFirst+Autofac)+Vue的项目框架之十一Swagger使用一
-
解决vue+springboot前后端分离项目,前端跨域访问sessionID不一致导致的session为null问题
-
从零开始搭建前后端分离的NetCore2.2(EF Core CodeFirst+Autofac)+Vue的项目框架之十数据库基础方法的封装
-
从零开始搭建前后端分离的NetCore2.2(EF Core CodeFirst+Autofac)+Vue的项目框架之九如何进行用户权限控制
-
基于Vue的前后端分离项目实践
-
基于【 springBoot +springCloud+vue】的项目之一 || 后端搭建
-
详解基于Vue,Nginx的前后端不分离部署教程
-
从零开始搭建前后端分离的NetCore2.2(EF Core CodeFirst+Autofac)+Vue的项目框架之六使用过滤器进行全局请求数据验证
-
从零开始搭建前后端分离的NetCore2.2(EF Core CodeFirst+Autofac)+Vue的项目框架之八MemoryCache与redis缓存的使用