! \2 e! Q9 _3 n( g1 ?; _7 P 0 }2 N* r5 M6 M" J% {" d, k优点 4 D5 n* `2 ~3 Z B$ @" S2 _这种模式下, **前后端的分工非常清晰, 前后端的关键协作点是AJAX接口。**看起来是如此美妙, 但回过头来看看的话, 这与JSP时代区别不大。复杂度从服务端的JSP里移到了浏览器的JavaScript,浏览器端变得很复杂。类似Spring MVC, 这个时代开始出现浏览器端的分层架构: I% L$ D+ R {& _6 p 2 n) z) X: K# w `# J1 a6 p m! W; i缺点 " e k- B- Q, i+ B1 Q- P# M7 R- C1 }) Z# t. \5 Q5 F
c: g. ^! s: g6 d
前后端接口的约定:如果后端的接口一塌糊涂,如果后端的业务模型不够稳定,那么前端开发会很痛苦;不少团队也有类似尝试,通过接口规则、接口平台等方式来做。有了和后端一起沉淀的接口规则,还可以用来模拟数据,使得前后端可以在约定接口后实现高效并行开发。 0 b8 B, y0 l- R( ?9 Q9 N, w前端开发的复杂度控制:SPA应用大多以功能交互型为主,JavaScript代码过十万行很正常。大量JS代码的组织,与View层的绑定等,都不是容易的事情。 3 @8 R& X2 Y# k/ Z$ `3 g( z( i3.3、前端为主的MV*时代( G- s3 e; N5 t% r
此处的MV*模式如下:' P* f- D# n' f9 P3 q
) W) R; X! v$ H1 l- `( |8 ` m* H% A% }. ?$ D% w. @ [MVC(同步通信为主) :Model、View、Controller' O' c6 v) ^+ x9 J( f
MVP(异步通信为主) :Model、View、Presenter 5 h3 F. L1 {8 o- lMVVM(异步通信为主):Model、View、View Model为了降低前端开发复杂度,涌现了大量的前端框架,比如:Angular JS、React、Vue.js、Ember JS等, 这些框架总的原则是先按类型分层, 比如Templates、Controllers、Models, 然后再在层内做切分,如下图:6 H" @2 T! L5 `4 G- c( r
8 y5 S- _! h5 Z7 w$ q- S. Y( v, U& }/ ]: k5 y# }5 y
t# [ l" W5 Y. A6 D0 l
! q% K- g7 ]' d Q* V0 K优点3 E0 s* B( D0 u4 z2 S, K2 y5 s2 _' }
9 u# F+ g- z M) p; {: y9 ?8 M6 f
% P4 o, Z7 x) {5 w' |
前后端职责很清晰:前端工作在浏览器端,后端工作在服务端。清晰的分工,可以让开发并行,测试数据的模拟不难, 前端可以本地开发。后端则可以专注于业务逻辑的处理, 输出RESTful等接口。 7 g( d. L6 y! w前端开发的复杂度可控:前端代码很重,但合理的分层,让前端代码能各司其职。这一块蛮有意思的,简单如模板特性的选择,就有很多很多讲究。并非越强大越好,限制什么,留下哪些自由,代码应该如何组织,所有这一切设计,得花一本书的厚度去说明。 ( W3 h/ f9 I% v# Q3 _! B部署相对独立:可以快速改进产品体验缺点( {' R: a& P& [0 X
代码不能复用。比如后端依旧需要对数据做各种校验,校验逻辑无法复用浏览器端的代码。如果可以复用,那么后端的数据校验可以相对简单化。7 m+ P& ?0 w5 b0 Z
全异步, 对SEO不利。往往还需要服务端做同步渲染的降级方案。0 D1 F/ P' Z1 Q3 d
性能并非最佳,特别是移动互联网环境下。, ~& }2 }5 L6 ~( e0 Z
SPA不能满足所有需求, 依旧存在大量多页面应用。URL Design需要后端配合, 前端无法完全掌控。 ' ~& E& L2 f% U' S; d3.4、Node JS带来的全栈时代. d- ^, q6 O" g5 A. X
前端为主的MV*模式解决了很多很多问题, 但如上所述, 依旧存在不少不足之处。随着Node JS的兴起, JavaScript开始有能力运行在服务端。这意味着可以有一种新的研发模式:! n- ^" m1 y1 D& d" S
6 V) g0 N9 ]* a% [! p% t; p' J ! l: c3 ~6 c, e q- q3 r在这种研发模式下,前后端的职责很清晰。对前端来说,两个UI层各司其职: . M5 |) p. v- ^4 M2 [# t0 e ; A9 ]: q# S* `* ]3 j. w" D3 [0 o6 o" B7 \6 h. X' ?) v" u
Front-end Ul layer处理浏览器层的展现逻辑。通过CSS渲染样式, 通过JavaScript添加交互功能, HTML的生成也可以放在这层, 具体看应用场景。 & x) v& b% \1 eBack-end Ul layer处理路由、模板、数据获取、Cookie等。通过路由, 前端终于可以自主把控URL Design, 这样无论是单页面应用还是多页面应用, 前端都可以自由调控。后端也终于可以摆脱对展现的强关注,转而可以专心于业务逻辑层的开发。& O3 M N9 p$ [ S' w" J: @( o
通过Node, WebServer层也是JavaScript代码, 这意味着部分代码可前后复用, 需要SEO的场景可以在服务端同步渲染,由于异步请求太多导致的性能问题也可以通过服务端来缓解。前一种模式的不足,通过这种模式几乎都能完美解决掉。 3 ^1 K; R6 L0 W0 J, L6 t5 |与JSP模式相比, 全栈模式看起来是一种回归, 也的确是一种向原始开发模式的回归, 不过是一种螺旋上升式的回归。( g, G: _3 w# R9 r
基于Node JS的全栈模式, 依旧面临很多挑战: . B/ _4 M. S7 m( D, k需要前端对服务端编程有更进一步的认识。比如TCP/IP等网络知识的掌握。 : u5 \* M% z1 j7 ] @& a5 ?; aNode JS层与Java层的高效通信。Node JS模式下, 都在服务器端, RESTful HTTP通信未必高效, 通过SOAP等方式通信更高效。一切需要在验证中前行。 ' W5 k: W, W, K% O对部著、运维层面的熟练了解,需要更多知识点和实操经验。 * C* }! y4 F5 K: X% i7 R& }大量历史遗留问题如何过渡。这可能是最大最大的阻力。( a9 O) R! n3 c, w% P7 j- \$ o
注:看到这里,相信很多同学就可以理解,为什么我总在课堂上说:“前端想学后台很难,而我们后端程序员学任何东西都很简单”;就是因为我们后端程序员具备相对完善的知识体系。. K. l ~! e4 s
全栈!So Easy! 8 ^3 d, M. l) T3.5、总结 % l4 ]2 B* F/ Z @综上所述,模式也好,技术也罢,没有好坏优劣之分,只有适合不适合;前后分离的开发思想主要是基于Soc(关注度分离原则),上面种种模式,都是让前后端的职责更清晰,分工更合理高效。 1 C2 F' P2 L& C1 J2 i$ V 5 m8 G! X/ a1 N5 h, x ) k% P0 G4 l' J4 K8 S, I5 }四、第一个Vue程序 , E9 v* U9 m6 x! } H4.1、什么是MVVM 2 `. c" o/ H: {2 S& FMVVM(Model-View-ViewModel)是一种软件设计模式,由微软WPF(用于替代WinForm,以前就是用这个技术开发桌面应用程序的)和Silverlight(类似于Java Applet,简单点说就是在浏览器上运行WPF)的架构师Ken Cooper和Ted Peters开发,是一种简化用户界面的事件驱动编程方式。由John Gossman(同样也是WPF和Sliverlight的架构师)与2005年在他的博客上发表。 4 g3 H7 |! ]: y+ O R4 }3 c6 h+ n1 m8 _: p6 Q) G" f# ?. |
MVVM源自于经典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用。其作用如下:# V6 d; r' l8 r1 u6 a9 P3 w
8 K0 z1 [- a2 U v; ?- E8 a% B! f( e) e1 t( d/ n2 U
该层向上与视图层进行双向数据绑定& i% y+ ]4 C1 x
向下与Model层通过接口请求进行数据交互 : Z0 d1 W1 R, `4 l ' `3 \" T- z @) a7 g 0 e. U- q& @9 \ u' a' G2 T3 T K' `
# ~7 d5 ~& E1 \2 u7 _2 d5 OMVVM已经相当成熟了,主要运用但不仅仅在网络应用程序开发中。当下流行的MVVM框架有Vue.js,Anfular JS 5 m" Z! ^ m0 m( c$ x0 m. G, R2 {$ b* O, I& ?0 l9 Z. l& h
6 r& f6 p/ V7 O* U6 ] c. h4.2、为什么要使用MVVM: O2 Z. Q# s1 A8 ]& V: _
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大好处$ q5 X! x1 A! k) I: [$ L
( A5 T$ M: y1 O+ o8 f5 u/ V ; @. L. p( E/ U# f0 C- y! a9 C低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。 6 y) \; `* k# N: o9 K c可复用:你可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑。% d+ g. I# w1 \. b
独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewMode),设计人员可以专注于页面设计。; _2 _# f/ l, X
可测试:界面素来是比较难以测试的,而现在测试可以针对ViewModel来写。 9 T% o/ k# W+ a$ B8 @5 h' T. |/ j1 _) H
/ h9 U5 a- ?2 I% {( R(1)View 7 `0 q6 b# |" R- |& l; v % D; {& x( ] m& D' J& g! W" \8 c 4 A) r- \8 t8 f$ i; j1 V6 Y' oView是视图层, 也就是用户界面。前端主要由HTH L和csS来构建, 为了更方便地展现vi eu to del或者Hodel层的数据, 已经产生了各种各样的前后端模板语言, 比如FreeMarker,Thyme leaf等等, 各大MV VM框架如Vue.js.Angular JS, EJS等也都有自己用来构建用户界面的内置模板语言。8 H5 X7 u8 }5 Y" y/ D$ A0 X
6 o: b+ R1 n4 p# n7 A! t% Q+ G
* O3 V4 w& c, J1 h% G8 a
(2)Model: W& z, ~4 Z3 H4 ^" g
6 W q1 I4 T3 C+ {8 T- K1 w/ v; o
+ {* Y2 \/ b+ V& IModel是指数据模型, 泛指后端进行的各种业务逻辑处理和数据操控, 主要围绕数据库系统展开。这里的难点主要在于需要和前端约定统一的接口规则2 E' ?) [% D" }+ S
! C" u S, B- m) \" X* E7 g9 v) S( r f* k W" ]8 d
(3)ViewModel # n! }6 H, `( m$ X* S, g2 U. @3 A0 m- T, [
" \& g( v' f3 _& ?. i/ A ( S8 ~$ z4 {" B}* M6 A0 x+ \1 @+ z0 G6 ?6 t# }' z! O
</script> 3 C- G$ a% M7 ^* T3 y8 y / @) Y0 Q3 G9 L5 |% k 2 ?! B& K8 R4 H" Y) g }<style>: ]* {' Y! k Y9 Y* G: G( m4 e
#app {+ K+ S/ N/ m8 S$ q Z
font-family: 'Avenir', Helvetica, Arial, sans-serif;% G. U5 `. h. g) g( i4 _& S
-webkit-font-smoothing: antialiased; 1 l# f, Y9 ^5 R -moz-osx-font-smoothing: grayscale; / r" X& w" c; m$ T) j; | text-align: center; 0 X* p, l6 r# n1 I6 s& M color: #2c3e50; % {; E. d. U4 C+ ^* [ margin-top: 60px; 5 J( {( p3 q/ e) H1 B} ! K% ~. ^; t( Y& `: B" n2 ?1 g</style>: `( p4 ?0 f9 X
1 6 C& ^' ^3 o [2% _, g7 P8 n3 }8 @9 K p
3; W$ T5 V- a9 A' h
4+ E- k f- O2 s) r* q z( v" e
5 5 ?: T3 Y N, t* A b' _6 / a# E. {' s9 {4 m7 4 E5 I' @! @, ^, ]4 n6 l8 & m+ T1 x( ~2 D" }1 x9 9 g! ~% A6 N4 p% F10 [5 u7 M& C5 Y1 B6 X- C* ~2 V11 - N( C- [# S2 ?3 o8 L12% M" g- R& j8 Q" X
13. c. {/ L" O. {, i0 }3 L& X* u
14 $ q! O7 v |( v7 V15! T7 F0 f# p9 `4 Y8 E4 g; b6 ?2 J
16 9 n9 e" M( ] V17 9 `2 v S3 V6 M" z1 y9 l5 m8 \18 ~' k; N6 a2 H+ O
190 o/ T3 Y. J* o2 f
20 o- r! X9 _/ e* ?' ?
21) b- d1 q: |- R; _
22( {8 \! L) T7 o; `( c
23 # X, a9 j* ]: ?' |0 S24 6 M, j$ q4 ~( A( E: ?/ s25 + X, A" I8 k! {0 W' N2 c4 emain.js$ M- E2 T& @8 k7 L4 I/ Z U* E4 y
' B, n& u0 h, r; W, u# u. I7 [ ( I" ^( T/ i0 ]) v- [2 t// The Vue build version to load with the `import` command ' e& Q% W' L! v+ U6 @// (runtime-only or standalone) has been set in webpack.base.conf with an alias.( M# B E+ n( F! L' U5 z
import Vue from 'vue'; A9 D1 y% g' D# ]0 f
import App from './App' % l1 B- ^+ |. V3 himport router from "./router"* I( ^" e1 {6 W% |; H
3 R! n* ^ ?) d; Z8 e9 D