我1998年開始學(xué)習(xí)Java,那時(shí)候?qū)W校里老師可能聽說過Java,但是同學(xué)基本上都不知道Java。校圖書館進(jìn)第一批Java的書,后面的借閱記錄上都是我的名字。當(dāng)時(shí)幾乎所有男同學(xué)都在學(xué)C++、PB、VB、Delphi,女生很多在學(xué)ASP。所以很多同學(xué)問我學(xué)的是什么,Java是干什么的。
大學(xué)畢業(yè)以后,開始用Java做的第一個(gè)實(shí)際項(xiàng)目是對(duì)日外包,是2001年。日方有一套很老的系統(tǒng),想用Java重構(gòu)一下,要求用JSP。我下班就跑去西單圖書大廈,發(fā)現(xiàn)那里的書都還是Servlet的, 沒有JSP的!
還好,當(dāng)時(shí)的公司同時(shí)進(jìn)行的一項(xiàng)業(yè)務(wù)就是代理BEA的Weblogic(BEA是三個(gè)從SUN出來(lái)的人創(chuàng)建的,后來(lái)被Oracle收購(gòu))。Weblogic的產(chǎn)品文檔里包含非常全面的JSP介紹,所以起初對(duì)JSP的學(xué)習(xí)都是從Weblogic開始的。
那時(shí)候還沒聽說過什么Struts。自己在SUN的官網(wǎng)發(fā)現(xiàn)了WAF的文檔,全稱是Web Application Framework,算是最早MVC模式的介紹。這個(gè)WAF不算是框架,只是介紹了MVC模式應(yīng)該是個(gè)什么樣子,如何用Servlet+JSP實(shí)現(xiàn)MVC模式。SUN的官網(wǎng)提供了少量的樣例代碼,剩下的都是我們根據(jù)文檔自己搭建和實(shí)踐。
在項(xiàng)目的中后期(02年下半年吧),有一次坐班車,聽到后面座位上兩個(gè)人在說話。一個(gè)人問:你知道Struts嗎?另外一個(gè)人說:不知道。問的那個(gè)人說:就是S T R U T S這幾個(gè)字母,開發(fā)Java的。我偷偷記在心里,然后第二天上網(wǎng)查了一下(當(dāng)時(shí)沒有智能機(jī),家里也沒有WIFI),才算開啟了Apache這扇大門。后來(lái)在ASF上又學(xué)習(xí)了Cocoon、pluto、turbine等等很多框架。
大概02年底,對(duì)日外包項(xiàng)目順利完成了,我公司開始接國(guó)內(nèi)的項(xiàng)目。第一個(gè)國(guó)內(nèi)項(xiàng)目是東北一所大學(xué)的科研經(jīng)費(fèi)審批項(xiàng)目。記得去給人家部署和演示的時(shí)候特別有意思。我們用了半天時(shí)間在服務(wù)器上部署好,然后去給客戶演示。打開瀏覽器,輸入ip+端口,開始操作。操作了十幾分鐘,所有的客戶沒有說一個(gè)字。越演示心里越?jīng)]底,不知道客戶啥反應(yīng)。大概又過了幾分鐘,客戶的主任發(fā)話了:你們的軟件呢?
我們的軟件呢?我給你演示了半天,這不就是我們的軟件嗎?最后才明白,用戶認(rèn)為只有下載一個(gè)類似叫setup.exe或install.exe的程序,雙擊,然后下一步下一步,最后桌面上出現(xiàn)一個(gè)快捷方式,那才算是軟件!在經(jīng)過片刻的不可思議之后,我認(rèn)為實(shí)際用戶的理念總是落后于研發(fā)人員的理念,這個(gè)我很容易想明白。但后來(lái)發(fā)現(xiàn),我那些學(xué)PB、Delphi的師兄弟也不是一時(shí)半會(huì)能接受B/S結(jié)構(gòu)的應(yīng)用算是軟件的...他們認(rèn)為:你不就是寫個(gè)網(wǎng)頁(yè)嗎???
再后來(lái),從03-08年,長(zhǎng)期從事企業(yè)應(yīng)用開發(fā),主要是基于Weblogic Platform,包括Server、Integration、Portal,其中在Portal上工作的時(shí)間最多。
其中04-05年用Weblogic Portal做深圳市最大的電子政務(wù)項(xiàng)目,06-07年用Weblogic平臺(tái)做廣東省電信的3G業(yè)務(wù)平臺(tái),08-09年用Aqualogic做南方電網(wǎng)的SOA。
Weblogic Server中集成了Struts,沒記錯(cuò)的話當(dāng)時(shí)是1.1版本。BEA把Struts做了升級(jí)和改造,可以在Weblogic Workshop中可視化開發(fā),就是下面這樣:
其中圓形代表Action,有Begin Action,End Action,還有普通的中間節(jié)點(diǎn)Action。BEA把Struts的這個(gè)升級(jí)稱作Java Page Flow(Java 頁(yè)面流)。一組這樣的圖形當(dāng)中包含的Action和JSP,會(huì)定義在一個(gè)擴(kuò)展名是.jpf的文件中。
后來(lái),BEA把JPF捐獻(xiàn)給了Apache,成為ASF下的一個(gè)開源項(xiàng)目Apache Beehive。
Welcome to Apache Beehivebeehive.apache.org
這個(gè)項(xiàng)目現(xiàn)在已經(jīng)停止更新了。
大概從06年開始,接觸到了YUI,也就是Yahoo User Interface,Yahoo開源的一套前端JS組件庫(kù)。從此算是開啟了我的前端之路。
07-08年開始用Extjs,作者說Ext就是Extension(擴(kuò)展)的意思,擴(kuò)展了YUI,提供了更豐富的適合企業(yè)開發(fā)的前端組件。但這時(shí)候,Extjs還僅僅是豐富的UI組件庫(kù),算不上框架。就是在JSP生成的HTML里面嵌入Extjs的組件。
09-11年用GWT,就是Google Web Toolkits。Google當(dāng)時(shí)的想法很先進(jìn),用Java開發(fā)前端UI,最終編譯成JS。有點(diǎn)類似于現(xiàn)在TS編譯成JS的過程,就是打算利用上Java的強(qiáng)類型、面向?qū)ο蟮忍攸c(diǎn)。這時(shí)候就已經(jīng)完全前后端分離了。可以說從08年之后我就再也沒寫過JSP,一個(gè)頁(yè)面也沒寫過。
10年開始用Bootstrap。這時(shí)候GWT的缺點(diǎn)就暴露出來(lái)了,CSS非常難改。直到13年初,開始用上了Angularjs。記得當(dāng)時(shí)在智聯(lián)招聘上發(fā)布職位的時(shí)候搜了一下,北京市只有用友和我們公司招聘Angularjs開發(fā)。后來(lái)就從Angularjs用到React,又用回Angular4,一直到現(xiàn)在都以最新版本的Angular為主,企業(yè)應(yīng)用和互聯(lián)網(wǎng)應(yīng)用都有開發(fā)。移動(dòng)開發(fā)主要用Ionic,React Native也用過。
為什么要詳細(xì)介紹我過去和JSP以及前端框架相關(guān)的開發(fā)經(jīng)歷呢?是因?yàn)槲蚁氡磉_(dá)一個(gè)觀點(diǎn):如果要客觀公正評(píng)價(jià)JSP是否還有必要用,特別是還有必要學(xué),需要一個(gè)真正長(zhǎng)期用過JSP(前后端不分離)開發(fā),也真正長(zhǎng)期用前端框架(前后端分離)開發(fā)的人才可以。
就像我在有些知乎答案下評(píng)論的那樣:
遇到這種情況,我總想起福特的名言:“如果我當(dāng)年去問顧客他們想要什么,他們肯定會(huì)告訴我:‘一匹更快的馬。’”
滿大街跑馬車的時(shí)代,福特問顧客需要什么,顧客就說需要一匹更快的馬。他們不知道汽車時(shí)代會(huì)給生活帶來(lái)怎樣革命性的變化。
在BP機(jī)時(shí)代,大家認(rèn)為有人戴BP機(jī)已經(jīng)很牛了。滿大街諾基亞摩托羅拉功能機(jī)的時(shí)代,大家也都覺得夠用了。問他們需要什么,他們估計(jì)會(huì)回答:充一次電能不能待機(jī)一個(gè)月?能不能把自己喜歡的MP3當(dāng)彩鈴?
我覺得要對(duì)比評(píng)價(jià)兩代產(chǎn)品,應(yīng)該給兩代產(chǎn)品都熟練體驗(yàn)過的人去判斷。從功能機(jī)時(shí)代過來(lái)的人,現(xiàn)在iphone都已經(jīng)用到第三部了,你再問他功能機(jī)夠不夠用。就拿一個(gè)兩代產(chǎn)品都具有的功能(比如都可以QQ聊天)對(duì)比,你愿意回到功能機(jī)時(shí)代還是繼續(xù)用智能機(jī)。
一直抱定JSP不撒手,沒動(dòng)力、沒能力學(xué)習(xí)前端技術(shù),沒有真正理解前后端分離開發(fā)模式的人,不可能得出公正全面的評(píng)價(jià)。
在校期間或參加培訓(xùn)班就學(xué)習(xí)了前端框架,參加工作后就開始前后端分離的人,也無(wú)法理解老人只用JSP或用JSP+JS前端UI組件的開發(fā)模式是個(gè)怎么回事。
上面兩種人,據(jù)我實(shí)際接觸中了解,大部分都認(rèn)為自己的開發(fā)模式是理所當(dāng)然的。就像我之前描述自己剛畢業(yè)時(shí)候的經(jīng)歷一樣。大部分客戶和我的一些同學(xué),理所當(dāng)然認(rèn)為雙擊setup.exe,然后下一步下一步才是軟件。而我理所當(dāng)然認(rèn)為B/S架構(gòu)的也是軟件,只是更便于開發(fā)和操作。
過去一年多,陸陸續(xù)續(xù)在知乎上回答了一些關(guān)于JSP的問題。當(dāng)然,我的回答都是建議淘汰JSP,新人小白一定不要再學(xué)JSP了。我現(xiàn)在集中把這些技術(shù)因素歸納一下。
一個(gè)現(xiàn)代主流Java Web應(yīng)用,不管前端、后端、還是微服務(wù)架構(gòu),都在淘汰JSP。
其中,我認(rèn)為Java服務(wù)器端主流技術(shù)還是Spring(Spring Boot + Spring MVC + Spring Cloud)。
下面三點(diǎn),第一點(diǎn)幾乎盡人皆知,第二點(diǎn)有一部分人清楚,第三點(diǎn)卻很少有人意識(shí)到。
前端框架已經(jīng)非常成熟和穩(wěn)定,不需要JSP
前后端分離已經(jīng)不是什么趨勢(shì)了,而是當(dāng)前B/S架構(gòu)開發(fā)的主流模式。前后端分離之后,前端只負(fù)責(zé)展現(xiàn)和交互,后端負(fù)責(zé)核心業(yè)務(wù)邏輯。前后端通過API進(jìn)行交互,并且最好符合RESTful風(fēng)格。服務(wù)器端把數(shù)據(jù)返回給前端就不再關(guān)心這些數(shù)據(jù)用在哪里、如何布局、什么樣式。
這個(gè)層面的原因非常容易理解,也是絕大多數(shù)討論JSP是否還有必要學(xué)的時(shí)候里都會(huì)提到的。
服務(wù)器端的Spring MVC/WebFlux 和 Spring Boot已經(jīng)開始拋棄JSP
從Spring 5開始,在原有的基于Servlet技術(shù)的Spring MVC之外增加了一個(gè)新的編程模型,就是Spring WebFlux。
Spring WebFlux是響應(yīng)式非阻塞的,而且不支持Servlet API,所以也就不支持JSP!
上圖左側(cè)是Spring 5新引入的Spring WebFlux,右側(cè)是大家熟悉的Spring MVC,兩者并列,Spring同時(shí)支持。
關(guān)于這一點(diǎn),可以看Stack Overflow上面來(lái)自Spring Framework和Spring Boot團(tuán)隊(duì)成員Brian Clozel的回答:
Spring WebFlux - no JSP support??stackoverflow.com
新的Spring WebFlux不支持JSP,那咱們不用就好了,至少Spring MVC還是支持JSP的啊。那我們繼續(xù)看。
如果我們繼續(xù)使用Spring Boot+Spring MVC開發(fā),那么Spring Boot對(duì)JSP是有限制的,看官方文檔怎么說的:
鏈接在這里:
Spring Boot Reference Guide?docs.spring.io
其中那行備注:
If possible, JSPs should be avoided. There are several known limitations when using them with embedded servlet containers.
盡可能避免用JSP。當(dāng)使用嵌入式Servlet容器時(shí),有一些已知的限制。
關(guān)于這些限制和如何繼續(xù)在Spring Boot中使用JSP,可以自己查一下,知乎里就有好多文章
Spring Boot對(duì)JSP有限制,那咱們就湊合用唄,反正我是寫Java的,我的發(fā)展方向是架構(gòu)師,我正打算學(xué)習(xí)微服務(wù),正在看Spring Cloud。那咱們就繼續(xù)看看Spring Cloud吧。
微服務(wù)架構(gòu)下更沒有JSP的用武之地
首先要明白Spring Boot和Spring Cloud的關(guān)系。可以先看我的這個(gè)回答:
Spring boot與Spring cloud 是什么關(guān)系??www.zhihu.com
還是看這張圖吧:
右側(cè)綠色的部分都是Spring Cloud的組成部分,不管是API Gateway、Config Dashboard,Service Registry,還是多個(gè)MicroServices,他們都是Spring Boot應(yīng)用!或者說Spring Boot是整個(gè)Spring Cloud的基石(其實(shí)也是Spring Cloud Data Flow的基石)。
哦,你明白了,因?yàn)橛蠸pring Boot對(duì)JSP的限制,而Spring Cloud的組成部分都是Spring Boot應(yīng)用,所以Spring Cloud也對(duì)JSP有限制。其實(shí)不僅僅是表面上這個(gè)原因,咱們繼續(xù)分析。
如果強(qiáng)行繼續(xù)在Spring Cloud環(huán)境中繼續(xù)使用JSP,那么JSP放在哪里?有兩種方案。
那怎么才算是使用Spring Cloud的正確姿勢(shì)?還是看上面那幅圖,這次關(guān)注左側(cè)三個(gè)灰色的部分。IoT(物聯(lián)網(wǎng) Internet of Things)、Mobile(移動(dòng)應(yīng)用)、Browser(瀏覽器端),這三個(gè)也是應(yīng)用啊。
我們?cè)倏匆环鶊D:
整個(gè)Spring體系的圖出來(lái)了。還是看左側(cè),Your App,也就是IoT(物聯(lián)網(wǎng) Internet of Things)、Mobile(移動(dòng)應(yīng)用)、Browser(瀏覽器端)這三類!
Browser就是前后端分離之后的前端應(yīng)用,獨(dú)立開發(fā)、獨(dú)立部署、只和服務(wù)器端有HTTP RESTful通信。
我們看看Spring官方給出的Spring Cloud例子,鏈接在這里:
Spring Projects?spring.io
customers-stores-ui是前端應(yīng)用,用Angularjs實(shí)現(xiàn)的。例子是便于學(xué)習(xí)的,不應(yīng)該引入額外的太多其他技術(shù)!為什么Spring官方的例子非要用上前端技術(shù)?不能只用服務(wù)器端開發(fā)人員熟悉的模板引擎解(包括JSP)來(lái)演示Spring Cloud嗎?
我們?cè)倏戳硗庖粋€(gè)例子,Spring的Petclinic大家都熟悉吧?Spring 官方例子:
spring-projects/spring-petclinic?github.com
官方的是Monolithic(單體)應(yīng)用,模板用的是Thymeleaf,自己去看代碼。
用Spring Cloud實(shí)現(xiàn)的版本:
Spring Petclinic community?github.com
前端有Angular和React兩種實(shí)現(xiàn),服務(wù)器端有Java和Kotlin兩種實(shí)現(xiàn),都沒有用服務(wù)器端模板。
同樣的問題。為什么演示Spring Cloud的開發(fā),要引入額外的前端技術(shù)?
答案都是同樣的,Spring Cloud就必須前后端分離開發(fā)!用JSP就無(wú)法完美拆分微服務(wù),無(wú)法利用微服務(wù)本應(yīng)帶來(lái)的各種優(yōu)勢(shì)。
總結(jié):
我曾經(jīng)在知乎某一個(gè)問題下總結(jié)過:現(xiàn)在JSP處于被前后端夾擊的狀態(tài),生存空間越來(lái)越小了。就算你不打算管前端,只想在服務(wù)器端有所建樹。微服務(wù)的前提也必須前后端分離。
放棄JSP吧,讓自己的路走的寬一些。如果死守JSP不放,服務(wù)器端只能停留在SSH/SSM階段,用Spring Boot+Spring MVC已經(jīng)是你的天花板了。
ExtJs框架是目前市面上采用比較成熟的js框架,有著諸多優(yōu)點(diǎn)特別適合用來(lái)實(shí)現(xiàn)一些內(nèi)部的管理信息系統(tǒng).ExtJs提供了一套組件來(lái)開發(fā)類似于windows桌面的單頁(yè)面系統(tǒng),其中desktop桌面的開始菜單按照后臺(tái)提供的數(shù)據(jù)動(dòng)態(tài)生成也是一個(gè)難點(diǎn),下面將對(duì)desktop桌面動(dòng)態(tài)開始菜單的生成進(jìn)行介紹。
ExtJs官方提供了desktop桌面的demo,其中關(guān)于開始菜單的生成是靜態(tài)的方式,在js腳本中設(shè)置好了固定的開始菜單內(nèi)容再生成開始菜單。<font color=red>本文的講解內(nèi)容均是在官方demo基礎(chǔ)上進(jìn)行的修改</font>
整個(gè)需要改進(jìn)的腳本只有兩個(gè)一個(gè)是根目錄下的App.js以及BogusModule.js,前臺(tái)與后臺(tái)之間通過Ajax交互,數(shù)據(jù)交換個(gè)是為json
后臺(tái)定義了Mids類,如下所示:
public class Mids { private String mid; //菜單id private String text; //菜單名詞 private String path; //菜單路徑 private List<Mid> subs; //子菜單 //Mid作為Mids內(nèi)部類 public class Mid { private String mid; private String text; private String path; } }
因此前后臺(tái)交互的json數(shù)組示例如下:
[{mid:”m1”,text:”菜單1”,path:”/m1”,subs:null},{mid:”m2”,text:”菜單2”,path:”/m1”,subs:[mid:”m21”,text:”菜單21”,path:”/m21”}]
接下來(lái)我們就要修改App.js這個(gè)js文件
getModules : function(){ // return [ // //new MyDesktop.Blockalanche(), // //new MyDesktop.BogusMenuModule(), // //new MyDesktop.BogusModule() // // ]; return mArr; }, //找到這段代碼并注釋掉部分行并修改為return mArr,其中mArr就是開始菜單模塊會(huì)在另一個(gè)js文件中定義
下面我們就看核心的BogusModule.js這個(gè)文件,這個(gè)文件定義了開始菜單的生成方式和類型
//首先需要定義一個(gè)模塊類型MyDesktop.BogusModule Ext.define( 'MyDesktop.BogusModule', { extend: 'Ext.ux.desktop.Module', init:function () {}, createWindow: function (obj) { var desktop=this.app.getDesktop(); createWindow(desktop,obj);//該方法另外定義 } });
菜單數(shù)組以及Menu模型與后臺(tái)傳遞的json數(shù)據(jù)進(jìn)行綁定
var mArr=[]; Ext.define('Menu', { extend: 'Ext.data.Model', fields: ['mid', 'text', 'path','subs'] }); //
定義了一個(gè)store采用Ajax方式與后臺(tái)進(jìn)行是數(shù)據(jù)交互store進(jìn)行數(shù)據(jù)加載并實(shí)現(xiàn)開始菜單動(dòng)態(tài)加載和綁定,并且生成桌面
var store=Ext.create('Ext.data.Store', { model: 'Menu', proxy: { type: 'ajax', url: 'menu', reader: 'json' } }); store.load({ scope: this, callback: function (r, op, success) { if (success) { for (var i=0; i < r.length; i++) { var menu=Ext.define('MyDesktop.materialMenu', { extend: 'MyDesktop.BogusModule', init: function () { var mm=this; //判斷是否有子菜單,有子菜單則設(shè)置為點(diǎn)擊無(wú)效 if (r[i].data.subs) { mm.launcher={ text: r[i].data.text, iconCls: 'bogus', handler: function () { //有子菜單則點(diǎn)擊無(wú)效 return false; }, menu: {items: []} }; //遍歷子菜單數(shù)據(jù)并生成子菜單項(xiàng) Ext.Array.each(r[i].data.subs, function (m, index, allItems) { mm.launcher.menu.items.push({ text: m.text, iconCls: 'bogus', handler: function (src) { var desktop=mm.app.getDesktop(); createWindow(desktop,src); }, //scope: this, src: m.path, windowId: m.mid }); }); } else { //沒有子菜單則設(shè)置點(diǎn)擊打開窗口 mm.launcher={ text: r[i].data.text, iconCls: 'bogus', handler: this.createWindow, scope: this, src: r[i].data.path, windowId: r[i].data.mid }; } } }); mArr.push(new menu()); } // 生成桌面 var myDesktopApp; Ext.onReady(function () { myDesktopApp=new MyDesktop.App(); }); } } });
定義對(duì)應(yīng)的打開窗口模塊,每個(gè)窗口模塊均內(nèi)嵌了一個(gè)iframe,通過該iframe可以加載其它頁(yè)面內(nèi)容
function createWindow(desktop,obj) { var win=desktop.getWindow('bogus' + obj.windowId); if (!win) { var iframeId='bogus_' + obj.windowId; win=desktop .createWindow({ id: 'bogus' + obj.windowId, title: obj.text, //width: 800, //height: 600, maximizable: true, maximized: true, closable: true, resizable: true, html: "<iframe id='" + iframeId + "' style='width:100%;height:100%;border:0px;margin:0px;padding:0px;' frameborder='0' src=''></iframe>", iconCls: 'bogus', animCollapse: false, constrainHeader: true, listeners: { afterrender: function () { document .getElementById(iframeId).src=obj.src; } }, buttons: [ { text: '刷新窗口內(nèi)容', handler: function () { document .getElementById(iframeId).src=obj.src; } }, { text: '切換窗口大小', handler: function () { win.toggleMaximize(); } }, { text: '關(guān)閉', handler: function () { win.close(); } }] }); } win.show(); return win; }
這樣就完成了ExtJs桌面的動(dòng)態(tài)開始菜單生成
作者 | 張旭乾 責(zé)編 | 夢(mèng)依丹
出品 | CSDN(id:csdnnews)
前端和后端開發(fā),哪一個(gè)更容易上手?我們時(shí)常會(huì)在各大技術(shù)論壇看到類似的提問。話說興趣是最好的老師,不實(shí)踐,你可能很難知道自己更喜歡哪一個(gè)?
從Java開發(fā)再到前端工程師,他在轉(zhuǎn)型路上遇到過哪些困難?本文作者張旭乾分享了他的轉(zhuǎn)型經(jīng)歷,以及他在學(xué)習(xí)前端開發(fā)過程中,遇到的問題和總結(jié)出來(lái)的一些經(jīng)驗(yàn),希望對(duì)你有所啟發(fā)。
在 2008 年的時(shí)候,我進(jìn)入大專學(xué)習(xí) Java 開發(fā),HTML 和 CSS 只是專業(yè)的附屬品。那時(shí),主要還是前后端一體化開發(fā),HTML 和 CSS 只是為了結(jié)合 Java 里的 Servlet 生成頁(yè)面。JavaScript 則完全沒有講。
2010 年快畢業(yè)的時(shí)候,我參加了五個(gè)月的 Java EE 培訓(xùn),在這期間了解了 HTML、CSS,以及一部分簡(jiǎn)單的 JavaScript DOM 操作和 jQuery,能夠編寫一些帶交互的頁(yè)面和 Ajax 異步請(qǐng)求。
在這期間,我沒有太重視 HTML/CSS/JS 基礎(chǔ)。因?yàn)楸旧韯側(cè)腴T,并不知道哪些重要,哪些不重要。在做項(xiàng)目的時(shí)候,頁(yè)面部分要自己在網(wǎng)上搜索 HTML 標(biāo)簽和 CSS 屬性的用法。對(duì)于 JS 部分,則只會(huì) jQuery,高級(jí)的語(yǔ)法(例如閉包、原型鏈)完全沒有概念,只知道該怎么定義變量,處理事件,做一些基本的邏輯處理。
我的第一份工作是 Java 開發(fā),當(dāng)時(shí)公司用的技術(shù)很新潮,算是前后端分離的雛形。頁(yè)面部分完全使用了 ExtJS 庫(kù),它提供了一組現(xiàn)成的 UI 組件,所有的數(shù)據(jù)都是通過 Ajax 來(lái)從后端獲取,后端則用 Java 的 Servlet 提供JSON 數(shù)據(jù)。
這份工作的主要難點(diǎn)是一開始不了解前后端分離的開發(fā)模式。由于是第一次嘗試完全在客戶端 JS 去請(qǐng)求數(shù)據(jù),所以理解起來(lái)需要一點(diǎn)時(shí)間,當(dāng)時(shí)閱讀了 ExtJS 相關(guān)的文檔,才大體的了解到這種開發(fā)模式。基本上是利用 Ajax 請(qǐng)求數(shù)據(jù),然后通過它內(nèi)置的 API 來(lái)填充 UI。后面隨著開發(fā)的功能變多,對(duì)這種模式也適應(yīng)了。
努力學(xué)習(xí)還是有回報(bào)的,過了三個(gè)月試用期之后,因?yàn)楣ぷ鞅容^出色,在拿到正式員工薪資的基礎(chǔ)上,又額外加薪了 10%。所以剛進(jìn)入公司的時(shí)候不要怕上不了手,主流的技術(shù)遇到不會(huì)的地方要善于自行查找資料解決,對(duì)于公司內(nèi)部的技術(shù)要勇于向前輩請(qǐng)教。
2010 年底從第一家公司離職,回到家里自己充電,學(xué)習(xí)了 PHP。因?yàn)楫?dāng)時(shí)建站非常流行,學(xué)了 PHP 既可以做個(gè)人站長(zhǎng),也可以通過自由職業(yè),為客戶建站來(lái)賺取收入。因?yàn)椴渴鹁W(wǎng)站的主機(jī)基本上都支持 PHP 和 ASP,而 PHP 更加流行,所以我就自學(xué)了 PHP,通過官方文檔,加上實(shí)戰(zhàn)并結(jié)合搜索引擎搜索問題來(lái)學(xué)習(xí)。學(xué)完了之后就在網(wǎng)上發(fā)了個(gè)廣告,提供個(gè)人建站服務(wù),此時(shí)的我還是全棧開發(fā)。
2011 年底左右,廣告發(fā)完了我就忘了,沒把它太當(dāng)回事。大年初六突然收到一個(gè)客戶的電話,需要做一個(gè)網(wǎng)站,這讓我興奮不已。我給這位客戶一共做了兩個(gè)網(wǎng)站:
一個(gè)是論壇,直接二次開發(fā)的,修改了一下樣式。
一個(gè)是質(zhì)量保證查詢系統(tǒng),從零使用 PHP + MySQL + jQuery + jQuery UI 進(jìn)行開發(fā)。
真正有挑戰(zhàn)的是第 2 個(gè)項(xiàng)目,頁(yè)面部分幾乎遇到了前端開發(fā)中全部常見的難題:
JS 代碼管理
當(dāng)時(shí) UI 部分選擇了和 jQuery 配套的 jQuery UI。jQuery UI 封裝了一組常見的 UI 組件,例如拖拽、對(duì)話框、按鈕等組件,可以少寫一些邏輯代碼。盡管如此,編寫出來(lái)的 JavaScript 文件還是亂七八糟,因?yàn)轫?yè)面上有很多表格組件,需要在獲取數(shù)據(jù)后,手動(dòng)去循環(huán)展示表格,并在刪除或修改的時(shí)候,還要修改 DOM 更新表格;另外還有其它邏輯,例如登錄、查詢等。
雖然代碼分散在了不同的 JS 里,但是有的頁(yè)面因?yàn)闃I(yè)務(wù)邏輯比較復(fù)雜,加上當(dāng)時(shí)我也不太了解 JS 的復(fù)用方式和邏輯,導(dǎo)致了很多重復(fù)的代碼。我還有當(dāng)時(shí)的源代碼,可以感受一下代碼的長(zhǎng)度(兩張圖片為同一 JS 文件的不同部分,這里通過縮略圖展示):
一個(gè) JS 文件中的代碼
兼容性調(diào)整
彼時(shí),瀏覽器主流的還是 IE,所以還是需要做一些兼容性調(diào)整。不過好在 jQuery 主打的就是兼容全部瀏覽器,所以 JS 方面沒有太大問題,剩下的就是 CSS。這個(gè)項(xiàng)目在 IE、Chrome、火狐下顯示的都不一致,后來(lái)查了一下,解決方法可以根據(jù)瀏覽器特定的語(yǔ)法,編寫只在特定瀏覽器能識(shí)別的 CSS 屬性,或者選擇器,也就是所謂的 CSS hacks。另外也可以使用瀏覽器特殊的 HTML 指令,加載不同的 CSS 文件,最終把頁(yè)面調(diào)成一致就可以了。
性能調(diào)優(yōu)
因?yàn)轫?xiàng)目頁(yè)面部分處理數(shù)據(jù)比較多,加上開發(fā)經(jīng)驗(yàn)有限,當(dāng)時(shí)也只是在代碼效率上進(jìn)行了優(yōu)化,例如減少不必要的循環(huán)操作等。
與客戶溝通需求
這個(gè)是開發(fā)的軟技能了,學(xué)會(huì)如何拒絕不合理的需求。因?yàn)楫?dāng)時(shí)我是第一次面對(duì)客戶,也沒有自信,所以客戶說改什么,我立刻就開始給他改。這期間客戶最常見的話術(shù)就是:“這個(gè)功能很簡(jiǎn)單,你做一下”,或者“這個(gè)問題很容易解決,花不了你幾分鐘”。當(dāng)時(shí)我真覺得功能或者問題挺簡(jiǎn)單的,但是實(shí)際操作起來(lái),發(fā)現(xiàn)要比想象的難多了。做了幾次之后,知道無(wú)論多簡(jiǎn)單的功能或問題,都會(huì)涉及很多的細(xì)節(jié),所以后面客戶再提要求的時(shí)候,我就把這些細(xì)節(jié)先說清楚,給他一個(gè)大概的完工時(shí)間,再加上新增的功能需要額外收費(fèi),客戶就會(huì)自己斟酌要不要做了。
網(wǎng)頁(yè)設(shè)計(jì)水平
還有一個(gè)意外,讓我學(xué)了一部分設(shè)計(jì)知識(shí)。在給這個(gè)客戶做質(zhì)量保證系統(tǒng)的時(shí)候,還要求附帶一個(gè)產(chǎn)品的官網(wǎng),客戶給我發(fā)了產(chǎn)品資料之后,我參考網(wǎng)上同品類的網(wǎng)站,幫他設(shè)計(jì)了一版,但是客戶以不夠大氣為由,讓我重新設(shè)計(jì),我又設(shè)計(jì)了一次,客戶還是覺得不夠好,反復(fù)幾次,似乎無(wú)法滿足他的需求,他就把官網(wǎng)這部分給別人做了。當(dāng)時(shí)我也有點(diǎn)憋氣,于是買了本《寫給大家看的設(shè)計(jì)書》,專門學(xué)習(xí)了一些設(shè)計(jì)原則,努力提高自己的設(shè)計(jì)能力。后來(lái)等客戶的官網(wǎng)上線之后,發(fā)現(xiàn)設(shè)計(jì)的也一般,大概是審美不同吧。
在自由職業(yè)后半段時(shí)間學(xué)習(xí)了其它的框架,那個(gè)時(shí)候 Bootstrap 3、Foundation 之類的 HTML/CSS 框架開始爆火,因?yàn)槭窒矚g學(xué)習(xí)新的技術(shù),我就去看了看它們的介紹,看到 Bootstrap 3 內(nèi)置了很多組件,并且不怎么需要寫 CSS,就學(xué)了一下 Bootstrap 3。Bootstrap 3 內(nèi)部使用了 LESS 這個(gè) CSS 預(yù)編譯工具來(lái)生成 CSS,如果要自定義它的樣式,還需要會(huì) LESS。我就又看了一下 LESS 的文檔,發(fā)現(xiàn)它提供了很多實(shí)用的功能,例如變量、繼承、嵌套等,感覺很有意思也順便學(xué)了。
從這里你就可以知道:前端庫(kù)是互相依賴的。如果直接看前端需要哪些庫(kù),那么零零散散的有一堆,但是當(dāng)你真的開始下手學(xué)習(xí)一個(gè)框架的時(shí)候,你會(huì)發(fā)現(xiàn)好多框架可以從一條線里牽出來(lái),構(gòu)成一個(gè)完整的開發(fā)工具庫(kù),這些自然就都掌握了。
前邊所有的經(jīng)歷,奠定了我轉(zhuǎn)型前端所需要的技術(shù)基礎(chǔ)。而在從事自由職業(yè)期間,我發(fā)現(xiàn)我還是喜歡看做得見的項(xiàng)目,從 0 設(shè)計(jì)界面,直至實(shí)現(xiàn)出來(lái),很有成就感,并且我也享受在設(shè)計(jì)過程中,靈感迸發(fā)的快樂,心底就有了想轉(zhuǎn)前端的火苗。不過第 2 份工作,從 2013 年到 2016 年,我仍然做的是 Java 開發(fā)。
真正讓我對(duì)前端產(chǎn)生興趣,是 2016 年去留學(xué)之后。在 2017 年第一個(gè)學(xué)期,有同學(xué)問我 React 的問題,我不太會(huì),于是就上網(wǎng)幫同學(xué)查,查著查著,就發(fā)現(xiàn)前端已經(jīng)獨(dú)立作為一個(gè)職業(yè)了,再接著從 React 文檔找問題的解決方案時(shí),發(fā)現(xiàn)之前我用 jQuery 的問題在 React 中全部都解決了,可以不用手動(dòng)維護(hù)數(shù)據(jù)和 UI 之間的同步了,這讓我感到很欣慰,發(fā)誓等這學(xué)期放暑假,就深入學(xué)習(xí)一下。
很快,暑假就到了,要兌現(xiàn)承諾開始學(xué)前端。當(dāng)時(shí)室友學(xué)了高級(jí) Web 編程,主要講的是 React,React 在那個(gè)時(shí)候還非常難用,應(yīng)該還是 React 15,需要手動(dòng)配置好多東西:Babel、Bower.js 之類的。看著室友遇到一個(gè)組件顯示不出來(lái),經(jīng)過一天的搜索解決方案,才發(fā)現(xiàn)是組件名大小寫不一致導(dǎo)致的,這個(gè)讓我有點(diǎn)對(duì) React 好感度降低,不想學(xué)了。
后來(lái)我就研究了一下 Vue,發(fā)現(xiàn)普遍的說法是:功能和 React 類似,但是國(guó)內(nèi)用 Vue 的多,國(guó)外用 React 的多。看了下 Vue 是華人尤雨溪開發(fā)的,很佩服,據(jù)說上手比較容易,于是就決定先看看 Vue?
在把 Vue 官方文檔基礎(chǔ)部分看完之后,結(jié)合 YouTube 的一些視頻所教授的開發(fā)方法,大概一周的時(shí)間,覺得可以上手了,就想了一下練習(xí)項(xiàng)目。當(dāng)時(shí)了解到 Vue 適合開發(fā)單頁(yè)應(yīng)用,看了一下單頁(yè)應(yīng)用的特點(diǎn),發(fā)現(xiàn)似乎就是網(wǎng)頁(yè)版 App 的概念? 于是,我就想著把當(dāng)時(shí)我用的最多的網(wǎng)易云音樂模仿一下。花了一周多的時(shí)間,實(shí)現(xiàn)了首頁(yè) UI、添加歌曲,播放、暫停、快進(jìn)、快退等功能,期間學(xué)會(huì)了 CSS flex 布局。
使用 Vue 仿網(wǎng)易云音樂(左)的最終界面(右)
后來(lái)發(fā)現(xiàn)網(wǎng)頁(yè)版的功能局限性比較大,想著能不能做成桌面端的。當(dāng)時(shí)室友在學(xué)校的課里學(xué) Electron,一個(gè)跨平臺(tái)的桌面開發(fā)框架,只用編寫 HTML? CSS 和 JavaScript ,就可以生成在 Mac、Windows、Linux 操作系統(tǒng)都能運(yùn)行的應(yīng)用。于是我又把應(yīng)用遷到了 Electron 上面。
從 Electron 這里也了解到了,Node.js 到底和瀏覽器 JS 運(yùn)行時(shí)到底有什么不同:在 Node.js 的環(huán)境下,可以訪問更底層的操作系統(tǒng)級(jí) API,例如訪問本地文件,這樣可以方便用戶自行添加音樂。
做這個(gè)項(xiàng)目的時(shí)候,也遇到了很多問題:
不知道什么時(shí)候需要定義成組件。剛剛接受這種組件化開發(fā)的方式之后,最大的難題就是怎么才知道該不該把一部分 UI 定義成組件。當(dāng)時(shí)的思路就是,我先把所有的頁(yè)面代碼都寫在入口組件里,后面再根據(jù)頁(yè)面的布局,把這個(gè)組件拆分成各個(gè)部分,例如側(cè)邊欄、播放列表、播放控制器等,這樣的分法似乎很合乎邏輯,不過這也帶來(lái)了一個(gè)問題。
組件和數(shù)據(jù)雜糅到了一起。項(xiàng)目當(dāng)時(shí)使用了 Vuex,應(yīng)用的數(shù)據(jù)全部交給了它去管理,對(duì)于項(xiàng)目的功能邏輯,都是直接在相關(guān)的 UI 中實(shí)現(xiàn)的,并綁定了 vuex 的數(shù)據(jù)。例如播放進(jìn)度條,它和歌曲的播放時(shí)間數(shù)據(jù)綁定了,后面要實(shí)現(xiàn)音量進(jìn)度條的時(shí)候,發(fā)現(xiàn)這個(gè)組件無(wú)法復(fù)用。因此,我又把 UI 和數(shù)據(jù)分離了出來(lái),這樣的組件,可以在各處復(fù)用,之后再實(shí)現(xiàn)對(duì)應(yīng)的邏輯就好了。
CSS Flex 布局遇到坑。這個(gè)項(xiàng)目使用了當(dāng)時(shí)開始流行的 CSS Flex 布局,本著學(xué)習(xí)的態(tài)度使用它,遇到了很多問題,例如父容器對(duì) flex 縮放的影響,如何讓 flex 元素占滿容器,又或是如何讓 flex 不占滿容器等等,這些在看了 MDN 文檔的介紹,了解了 flex、align-items 和 justify-content 各個(gè)屬性值的作用和含義之后,就清楚了元素的縮放邏輯。
通過這個(gè)小項(xiàng)目的開發(fā),對(duì) VUE 算是入門了,還得出了結(jié)論:
學(xué)前端,或者任何編程知識(shí),一定要結(jié)合實(shí)踐才能快速入門并掌握它們。
學(xué)完 Vue 之后暑假差不多也快結(jié)束了,最后一個(gè)學(xué)期都在努力學(xué)專業(yè)課,沒有再看前端相關(guān)的東西。2018 年回國(guó)之后,開始找工作。因?yàn)榱魧W(xué)的主要方向是分布式和云計(jì)算,所以我還是想以 Java 開發(fā)為主。面試的時(shí)候遭到了很多不屑,大多是看我剛研究生畢業(yè),而以前的開發(fā)經(jīng)歷也沒什么出彩的地方,就都草草了事了。這些經(jīng)歷讓我很受打擊,但是讓我清楚的知道了,縱使有一肚子墨水,但是拿不出實(shí)際的產(chǎn)品,或者滿足不了面試官的喜好,就不可能面試成功。
當(dāng)然我不會(huì)否定自己,最后一次面試失敗之后,突然就想要不要改行做一下前端,畢竟留學(xué)的時(shí)候鉆研了不少,又在自由職業(yè)的時(shí)候做過一些產(chǎn)品,更是有濃厚的興趣,于是我立刻下了決心轉(zhuǎn)前端。
下定決心之后,我一刻也沒閑著,開始看前端的工作要求。在某招聘 App 上搜了一圈,發(fā)現(xiàn) React 在大廠用的多、工資也高一點(diǎn),我就又開始自學(xué) React,花了一周看了看官方文檔,寫了一個(gè)特別小的、只有一個(gè)頁(yè)面的小例子,之后就開始投簡(jiǎn)歷了。期間還看了看 React Router、Redux,以及 ES6 的新特性。
在閱讀 React 官方文檔的時(shí)候,發(fā)現(xiàn)有一節(jié)是《Thinking in React》,里邊詳細(xì)的介紹了 React 組件化開發(fā)的步驟,并且解釋了什么時(shí)候需要定義組件,文檔提供了一個(gè)表格 UI 作為示例,把它拆解成了表格整體、搜索框、表格內(nèi)容、類別行和產(chǎn)品行組件,說明了為什么這么拆解,有沒有其它拆解的方法,以及拆解過程的方案折中,建議看一看。
圖片來(lái)源:https://reactjs.org/docs/thinking-in-react.html
覺得準(zhǔn)備的差不多了之后,就開始投簡(jiǎn)歷了,大約 1 個(gè)月的時(shí)間,收到 3 家面試,只通過了 1 家。沒過的那兩家同樣也是見我剛畢業(yè),連前端開發(fā)經(jīng)驗(yàn)都沒有,就草草了事了。通過的這家,面試官是我工作時(shí)的技術(shù)總監(jiān)和組長(zhǎng),在面試的時(shí)候沒有刻意刁難,只是問了些框架方面的基礎(chǔ)問題,還問了一下我平時(shí)是怎么解決問題的。后來(lái),我在工作的時(shí)候,問他們?yōu)楹螞Q定讓我入職,他們告訴我,看中了我的學(xué)習(xí)能力。
所以面試如果沒經(jīng)驗(yàn)的話,就努力說明自己的學(xué)習(xí)能力,總會(huì)有面試官欣賞你的。我到現(xiàn)在還非常感謝兩位,讓我正式進(jìn)入了前端開發(fā)的行列。
進(jìn)了公司就開始了日常做項(xiàng)目,大大小小一共做了 3 個(gè),這期間經(jīng)歷了邏輯混亂期、嘗到甜頭期和精進(jìn)技術(shù)期,積累了大量的開發(fā)經(jīng)驗(yàn)。
第 1 個(gè)項(xiàng)目,是改造一個(gè)傳統(tǒng)的項(xiàng)目,按技術(shù)總監(jiān)的建議,使用 React + dva.js 框架。UI 方面,項(xiàng)目之前用的是 Bootstrap,我用了 React Bootstrap 把項(xiàng)目遷移了過來(lái)。
這個(gè)項(xiàng)目里遇到的問題是:代碼混亂。這個(gè)時(shí)期因?yàn)閯倓偵鲜?React 開發(fā),對(duì)于代碼的管理也沒有太大的概念,加上 dva.js 的項(xiàng)目結(jié)構(gòu)也不同于普通的 React 項(xiàng)目,所以這個(gè)項(xiàng)目開發(fā)起來(lái)有點(diǎn)麻煩,再加上項(xiàng)目的邏輯比較多,導(dǎo)致組件的代碼很長(zhǎng)很長(zhǎng),復(fù)用起來(lái)也很困難(俗稱面條式代碼),不過因?yàn)檫@個(gè)項(xiàng)目也不是完全對(duì)外公開的,并且使用頻率較低,所以就沒在優(yōu)化。
第 2 個(gè)項(xiàng)目,是做一個(gè)公司內(nèi)部用的運(yùn)營(yíng)管理后臺(tái),時(shí)間大約是 2018 年底,當(dāng)時(shí) React alpha 測(cè)試版出了 hooks。看了一下官方文檔,感覺很神奇,能夠清晰地分離組件 UI 和邏輯,應(yīng)該能給代碼管理提供不小的幫助。雖然是測(cè)試版,但這個(gè)項(xiàng)目是完全對(duì)內(nèi)的后臺(tái)項(xiàng)目,所以果斷的用上了。
這個(gè)項(xiàng)目的后端比較特殊,一位大佬同事搭建了 GraphQL 服務(wù),之前在留學(xué)的時(shí)候就已經(jīng)聽同學(xué)提到過很多遍了,現(xiàn)在有機(jī)會(huì)體驗(yàn)體驗(yàn)了。在看 GraphQL 官方文檔學(xué)習(xí)、以及使用搜素引擎搜索的時(shí)候發(fā)現(xiàn),使用 GraphQL 后可以不用 Redux,于是這個(gè)項(xiàng)目我只用了 React? React Router 和 Apollo-GraphQL 這幾個(gè)主要的庫(kù)。
這套技術(shù)加上 React hooks,讓我真正感受到了前端開發(fā)的樂趣。組件從類的形式轉(zhuǎn)換成了函數(shù)形式,代碼量減少了很多,公共的邏輯也能抽離成 Hooks,在各個(gè)組件使用,組件自身的邏輯也能抽離成 hooks,來(lái)讓功能和 UI 展示代碼分開,讓代碼更易讀。這樣,整體的開發(fā)效率提高了不少。
UI 方面則嘗試了 Ant Design,因?yàn)榧兒笈_(tái)的,沒有設(shè)計(jì)稿,只有產(chǎn)品原型。
另外這個(gè)項(xiàng)目是基于 Create-React-App 腳手架創(chuàng)建,了解到腳手架提供的功能非常全面,像靜態(tài)資源(圖片、字體)管理、插件、打包構(gòu)建等都包括了,省了很多手工配置。
第 3 個(gè)項(xiàng)目,是一個(gè)從 0 開始、面向客戶的應(yīng)用,UI 是由設(shè)計(jì)師專門設(shè)計(jì),有很多自定義的樣式。這是我積累最多前端開發(fā)經(jīng)驗(yàn)的項(xiàng)目,從技術(shù)選型,到組件規(guī)劃,再到代碼復(fù)用,對(duì)前端開發(fā)的架構(gòu)有了全新的認(rèn)識(shí)。
為了研究怎么在 React 項(xiàng)目中管理樣式最方便,我開始研究大型項(xiàng)目中的 CSS 樣式管理,了解到有普通 CSS 和 CSS-in-JS 兩種方案之后,再查資料發(fā)現(xiàn) CSS-in-JS 方案更靈活,能夠在 CSS 里訪問 JS 變量,讓組件樣式可以隨著組件狀態(tài)的變化而變化。
決定用 CSS-in-JS 方案之后,我找到了 GitHub Star 數(shù)比較高的 styled-components 庫(kù),它支持 CSS 嵌套、主題等功能,并且能夠訪問組件的屬性,而且它定義的樣式,本身也是一個(gè) React 組件,可以直接在 JSX 中使用。
UI 庫(kù)繼續(xù)使用了 Ant Design,不過也就是利用一下它的組件功能邏輯,樣式幾乎全部都修改了。
項(xiàng)目后端這次沒有用 GraphQL,我又發(fā)現(xiàn)不用 GraphQL 也沒必要使用 Redux,所以就沒有再添加 Redux,結(jié)果也證明我的選擇是對(duì)的:項(xiàng)目本身沒太多全局狀態(tài),舍棄 Redux 大概讓開發(fā)效率提升了 1 倍,之前像表單這樣的組件大概需要一天才能完成,現(xiàn)在只需要半天。不過項(xiàng)目里有個(gè)內(nèi)嵌的聊天系統(tǒng),需要用一點(diǎn)全局狀態(tài),我就從網(wǎng)上查找了一些解決方案,發(fā)現(xiàn)使用 React Context + useReducer Hooks 的方式實(shí)現(xiàn)全局狀態(tài)管理就夠了。
這個(gè)項(xiàng)目使用的新框架都是一邊看官方文檔一邊學(xué)習(xí)的,有不好解決的問題,就結(jié)合搜索引擎和 GitHub Issues 解決。
對(duì)于項(xiàng)目的結(jié)構(gòu),這次使用了就近原則來(lái)組織代碼,每個(gè)組件放到單獨(dú)的文件夾中,組件相關(guān)的 styles、圖片、hooks 等都放在同一個(gè)文件夾,對(duì)于公用的部分,則放到項(xiàng)目頂級(jí)的 src 目錄下。API 和其它庫(kù)的配置項(xiàng)也都放到單獨(dú)的文件夾里,同樣遵循就近原則,這樣管理項(xiàng)目就方便多了。
這個(gè)項(xiàng)目的圖表也比較多,為了和 App 端保持一致,選擇了 Echarts。在使用 Echarts 的時(shí)候,雖然能夠?qū)崿F(xiàn)大部分設(shè)計(jì)稿中的樣式,但是還是有小部分不能精準(zhǔn)還原,在拿著實(shí)際效果跟設(shè)計(jì)師溝通之后,有些樣式就做了些調(diào)整,或直接舍棄了。
項(xiàng)目最后驗(yàn)收的時(shí)候,還需要跟 UI 設(shè)計(jì)師核對(duì)樣式,這期間我和設(shè)計(jì)師找了單獨(dú)的工位,每天都是在溝通哪里的設(shè)計(jì)需要修改,哪里的設(shè)計(jì)不好實(shí)現(xiàn),怎樣取一個(gè)大家都滿意的折中方案。這些在了解設(shè)計(jì)基礎(chǔ)原則之后,你也會(huì)明白設(shè)計(jì)師設(shè)計(jì)的意圖和用意,這樣用理解的心態(tài)來(lái)溝通,再輔以技術(shù)上的難度展示和時(shí)間需求,就能夠更好的避免不必要的 UI 改動(dòng)和代碼重構(gòu)。
先看一下前端工程師需要掌握哪些技能。
綜合大、中、小企業(yè)的前端工程師技能需求,實(shí)際上前端工程師的職能包含以下職業(yè)中的 1 種或多種:
網(wǎng)頁(yè)開發(fā)工程師
網(wǎng)頁(yè)設(shè)計(jì)師(UI)
用戶體驗(yàn)工程師(UE)
最重要的職能是網(wǎng)頁(yè)開發(fā),包括小程序、APP 等跨端應(yīng)用界面的開發(fā),雖然它們實(shí)現(xiàn)的技術(shù)不同,但本質(zhì)上還是做頁(yè)面。
前端工程師必備的技能有:
使用 HTML + CSS,精準(zhǔn)地還原設(shè)計(jì)稿,制作符合要求的頁(yè)面。
使用 JavaScript 給頁(yè)面添加交互,懂得 DOM 操作和 Ajax 請(qǐng)求。
掌握 React 或 Vue 等主流框架的一種或幾種,并了解隨著這些框架的工程化,所牽涉的一系列工具(不同工程需要不同的工具,這里列出常見的), 例如:
Node.js 與 npm。
Webpack、SnowPack、Vite 等打包工具。
Create React App、Vue CLI、Vite 等腳手架。(Vite 既包含腳手架,也包含打包工具)
Gulp、Grunt 等自動(dòng)化工具。
SASS/LESS 等 CSS 預(yù)編譯工具。
styled-components、emotion 等 CSS-In-JS 庫(kù)。
ESLint 語(yǔ)法檢查工具。
Jest、mocha 等測(cè)試庫(kù)。
兼容性調(diào)整,利用 CSS hacks,或 JS Polyfill,實(shí)現(xiàn)跨瀏覽器頁(yè)面表現(xiàn)一致。
性能優(yōu)化,減少文件體積,減少請(qǐng)求次數(shù),延遲加載圖片和腳本等。
SEO 搜索引擎優(yōu)化,提高網(wǎng)站在搜索引擎的排名。
其他的一些框架或技能,如果工作要求,也需要掌握:
SSR 服務(wù)端渲染框架,例如 Next.js(React)、Remix.js (React)、Nuxt.js(Vue)。
SSG 靜態(tài)網(wǎng)站生成器,例如 Next.js、Gatsby、VuePress 等。
TypeScript。
GraphQL。
PS/Sketch/Figma,能根據(jù)需要進(jìn)行切圖,或者自行設(shè)計(jì)頁(yè)面。
下面這些技能不是必須的,但是如果能掌握,可以提高工作效率、跟后端或設(shè)計(jì)師溝通的能力,以提升求職升職的競(jìng)爭(zhēng)力:
網(wǎng)頁(yè)設(shè)計(jì),了解設(shè)計(jì)基本原則。
用戶體驗(yàn)設(shè)計(jì),了解網(wǎng)頁(yè)的動(dòng)效、輔助功能對(duì)用戶體驗(yàn)的影響。輔助功能(可訪問性)在國(guó)外比較重視,目的是方便有閱讀障礙的人士,使用屏幕閱讀器進(jìn)行網(wǎng)站瀏覽。如果你想去外企,這些技能是必須要掌握的。
Docker,了解如何把前端項(xiàng)目構(gòu)建為 docker image,會(huì)編寫簡(jiǎn)單的 docker file。
后端語(yǔ)言、框架、數(shù)據(jù)庫(kù),任選一套,例如 Java + Spring + PostgreSQL,Express + Node.js + MongoDB 等,了解 RESTful API 開發(fā)過程。
乍一看要掌握的有很多,但很多庫(kù)都是隨著 React、Vue 等最重要的前端庫(kù)自然而然地引入進(jìn)來(lái)的,大部分的用法都很簡(jiǎn)單,并且我們還會(huì)在工作中持續(xù)學(xué)習(xí),一開始只需要入門就行。下圖展示了 React 前端開發(fā)工程師,根據(jù) React 框架所衍生的技術(shù)棧(示意):
React 前端工程師技能圖譜(示意)
2019 年從公司再次離職,不想再打工了,借鑒在國(guó)外留學(xué)時(shí)所學(xué)到的經(jīng)驗(yàn),轉(zhuǎn)型開始做視頻和線上教學(xué),運(yùn)營(yíng)著“峰華前端工程師”賬號(hào),同時(shí)也在 CSDN 發(fā)表博客。在這期間還撰寫了《JavaScript 基礎(chǔ)語(yǔ)法詳解》一書。
編寫書籍的時(shí)候,又是一次學(xué)習(xí)的過程,在查閱各種資料之后,對(duì) JavaScript 有了更完全的認(rèn)識(shí)。同時(shí)也明白了,人只有存在目標(biāo)的情況下,才會(huì)有動(dòng)力去完成看似不可能的事,避免渾渾噩噩度日。
如果你像我一樣,也算比較大齡的程序員,有年齡焦慮,可以適當(dāng)?shù)南胂脒€要不要在公司里繼續(xù)工作下去,是不是該拿出勇氣來(lái)嘗試做自己真正想做的事,之后利用興趣養(yǎng)活自己。這不是一條容易的路,所以在決定之前一定要做好兩年之內(nèi)沒有起色的打算,這些如果我能總結(jié)出一套經(jīng)驗(yàn)之后,再來(lái)分享。
這些大體就是我學(xué)習(xí)、掌握前端開發(fā)的過程,總結(jié)了下面這些重點(diǎn):
學(xué)會(huì)獨(dú)立學(xué)習(xí)。前端的框架太多了,并且經(jīng)常出現(xiàn)新奇特框架,必須要能自己獨(dú)立通過官方文檔和搜索引擎進(jìn)行學(xué)習(xí),因?yàn)榍岸丝蚣芏鄶?shù)比較小眾,不會(huì)有很多相關(guān)的教程。如果連文檔都沒有,就要學(xué)會(huì)讀源碼學(xué)習(xí)用法。
基礎(chǔ)打牢。前端庫(kù)雖然多,但萬(wàn)變不離其宗,總是要回歸到 HTML、CSS 和 JavaScript 上面,所以基礎(chǔ)一定要打牢,尤其是在 ES6 以后出現(xiàn)的新特性,在前端用途非常廣泛。
實(shí)戰(zhàn)練習(xí)。學(xué)完前端庫(kù)之后,一定要找個(gè)小項(xiàng)目做,把學(xué)到的東西真正地掌握。Github 上有很多前端項(xiàng)目靈感的庫(kù),可以搜索 “front-end project ideas" 找到 ,或者你也可以改造模仿市面上的網(wǎng)站、App 等。
不要把前端只局限在技術(shù)層面。向上往設(shè)計(jì)和產(chǎn)品擴(kuò)一下,向下從后端和運(yùn)維鉆一下,你會(huì)更能從整體角度觀望整個(gè)項(xiàng)目,從而在前端技術(shù)選型、開發(fā)過程以及和同事溝通的時(shí)候,懂得取舍和折衷。
線上文檔。對(duì)于 HTML、CSS 和 JavaScript 最權(quán)威的文檔就是 MDN。其它的像 React、Vue 等框架,就是官方文檔。如果遇到了問題,就去搜索引擎搜索,看其他人寫的解決方案。
書籍。對(duì)于體系化的教程,可以購(gòu)買相關(guān)的書籍看,重點(diǎn)看專業(yè)、經(jīng)典的書籍,這些網(wǎng)上有很多推薦。書籍可以幫助你快速入門并深入,不用在網(wǎng)上東找西找了。
視頻。現(xiàn)在視頻平臺(tái)正火爆,不要只用來(lái)消遣,上邊也會(huì)有很多編程相關(guān)的視頻,空余時(shí)間可以刷一刷,可能會(huì)獲得一些開發(fā)靈感、技巧,以及未來(lái)工作可能用到的新技能。
在線課程或培訓(xùn)。在線課程或者培訓(xùn)能幫你直接學(xué)到和就業(yè)相關(guān)的技能,積累項(xiàng)目實(shí)戰(zhàn)經(jīng)驗(yàn),但是要注意鑒別課程和機(jī)構(gòu)的質(zhì)量。
向有經(jīng)驗(yàn)的人學(xué)習(xí)。如果你看到有高級(jí)工程師發(fā)布的博客、微博、視頻等內(nèi)容,可以嘗試和他們建立聯(lián)系,拿出你學(xué)習(xí)的誠(chéng)意,讓他們幫你指點(diǎn)迷津,或許能少走一些彎路。
END
成就一億技術(shù)人
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。