這幾天我一直在看代碼醋旦,看了一部分。整體感覺会放,代碼寫得很不優(yōu)雅浑度,沒有賞心悅目的感覺,綜合我之前寫react鸦概、vue箩张、以及一些設計模式和重構的經(jīng)驗,我有以下幾點建議:
1. 所有的資源依賴用絕對路徑
項目中有很多資源窗市,都是分類或就近存放的先慷,一個模塊有很多的依賴,寫依賴路徑的時候有兩種方式咨察,一種是絕對于項目根目錄的路徑论熙,一種是相對的相對當前目錄的路徑,如果是就近的依賴摄狱,那么相對的路徑是好一些脓诡,比較簡短。但是我推薦模塊所有的依賴都用絕對路徑媒役。這樣的好處是無論你把這個模塊放到什么地方祝谚,都不需要去改依賴的路徑,另外webpack提供了resolve的option酣衷,可以自己定義一些alias交惯,這樣我們的絕對路徑可以寫的更方便靈活。
現(xiàn)在項目中的依賴都是相對路徑穿仪,如下所示:
如果重構的時候席爽,想改動文件結構簡直麻煩死,
webpack提供了resolve的alias的功能:
上面的依賴改成絕對路徑以后是這樣:
這樣看起來啊片,哪個依賴在哪也非常清晰只锻,不需要../../一層層去翻看目錄了。而且再也不用擔心重構的文件結構的改動了紫谷,隨便移到什么位置都不需要去改依賴的path齐饮。
2. 使用action creator抽離組件構造action的代碼
vue組件和 vuex的交互就是通過 action和mutation,但是生成 action的payload的過程可能會比較復雜碴里,需要對數(shù)據(jù)做一些轉換過濾之類的沈矿,這些代碼在組件中會顯得很冗余,占據(jù)了很多代碼量咬腋, 其實這些不是主要的邏輯羹膳,是一些比較瑣碎的工作, 我建議 在組件的同一層次建立 actionCreator.js 或者 mutationCreator.js來封裝這個過程根竿。其實這是redux技術棧的架構會有的一個東西陵像,在vue技術棧也同樣可以適用就珠。
比如,現(xiàn)在組件中有這樣的代碼:
如果把這個抽取到actionCreator中醒颖,會變成這樣:
多了一個actionCreator妻怎,使得代碼簡潔易讀不少。mutationCreator也是同樣泞歉。
3.mock data使用mockjs的模板語法和隨機api逼侦,并且加上接口文檔鏈接
mockjs提供了很多生成mock數(shù)據(jù)的強大功能,包括生成各種隨機數(shù)據(jù)和重復規(guī)則兩方面腰耙。
比如:
更多示例見: http://mockjs.com/examples.html
我們項目中使用了mockjs榛丢,卻沒用用他的api和模板語法,有種入寶山空手而歸的感覺挺庞。
如果用了mockjs的隨機api和重復語法之后晰赞,是這樣的:
生成的數(shù)據(jù)更加的隨機、貼近真實选侨,控制重復次數(shù)也更容易掖鱼。當然,真實的情況并不需要所有的數(shù)據(jù)都隨機援制,這里只是示例戏挡。
還有,因為mock數(shù)據(jù)中沒有注釋隘谣,雖然生成了正確的數(shù)據(jù)返回增拥,但是卻沒有對每個字段的值的解釋包括對接口的解釋、請求方式等內容寻歧,理解成本很高。這些都是寫在接口文檔中的秩仆,寫mock數(shù)據(jù)的時候可以順手把文檔的鏈接貼在文件里码泛,像這樣:
小小的改變,大大的不同澄耍,能提升很多效率呢噪珊,個人覺得。
4. 減少無用的Promise包裝
Promise可以讓我們的異步代碼的回調函數(shù)變成then的鏈式調用齐莲,幾乎所有的異步api都會設計成Promise的形式痢站,我們寫代碼的時候也是一樣,同時返回Promise對象的方法還可以使用 async选酗、await來進一步簡化阵难,用同步的方式來書寫異步代碼。
理論上來說 Promise是可以無限層嵌套的芒填,就像同步的無限賦值一樣:
let a = a;
b=a ;
c=b;
a=c;
但是這樣的代碼是沒意義的呜叫,雖然沒錯空繁,異步的類似代碼如下:
const func = () => {
return new Promise( (resolve, reject) => {
return new Promise( (resolve, reject) => {
return new Promise( (resolve, reject) => {
//...
});
})
})
}
我們的項目中就有很多這種代碼:
axios的返回值已經(jīng)是一個Promise對象了筷弦,為什么要再包裝一層乒省,沒必要的。
5. 正確理解components夷蚊、utils娱颊、common的不同
components是存放一些組件的傲诵,這些組件復用性比較高,比如一個Modal組件箱硕。
common是存放一些公共的代碼的掰吕,這些公共的代碼往往是很多個模塊用到,同時與代碼的組織結構有關系的颅痊,比如 一個公共的父類殖熟,一些公共的 filters、directives等斑响。
utils存放的是業(yè)務無關的一些工具方法菱属, 比如stirngUtils,dateUtils舰罚,validatorUtils等等纽门。
我們項目中有一些代碼存放的位置不對,比如 components下存放了 代理http的 fetch(應該放到common中)营罢。
比如api下的代碼除了各種請求相關的還有一些業(yè)務邏輯代碼(這個應該作為action handler放到store下)赏陵。
總之,業(yè)務代碼需要保持純粹饲漾,非業(yè)務相關的邏輯應該抽取出來分類存放蝙搔,但是具體放在哪要根據(jù)功能、封裝形式等來決定考传。
6. 引入 lodash作為工具庫
我們寫的代碼其實是有很多可以封裝簡化的空間的吃型,如果是原始的代碼,有很多顯得笨拙的地方僚楞,這時候用一個工具庫可以把很多代碼給簡化勤晚,看上去更加的簡潔。用一個開源的流行的工具庫也比自己封裝效率更高泉褐、bug也更少赐写。比如lodash就封裝了針對
各種類型很多場景下的一些邏輯,比如節(jié)流debounce膜赃、比如深復制deepClone挺邀、深比較deepCompare等。
我們的代碼有一些寫的不是很優(yōu)雅的地方,比如:
這段邏輯如果基于lodash寫的話悠夯,是這樣
簡潔優(yōu)雅了很多癌淮。當然這里用解構賦值更好一些,我只是舉一個栗子沦补。
好的代碼一定是經(jīng)過封裝的乳蓄,用一個開源的可靠的工具庫比自己封裝靠譜的多。
7. 組件封裝的粒度更細一些夕膀,使得一眼能看清組件層次
組件的意義所在就在于復用虚倒,拆分是復用的基礎,一個頁面可以拆分成很多的組件产舞,然后有機的組合這些組件就可以拼出我們的頁面魂奥。拆分組件的粒度還與性能有關系,在react中易猫,生成虛擬dom是需要判斷組件的shouldComponentUpdate的返回值的耻煤,更細粒度的封裝能夠減少不必要的渲染,這叫做短路優(yōu)化准颓。同時也會使得組件結構更加清晰哈蝇,比如
這樣比寫到一起結構清晰很多,而且在react中也利于優(yōu)化性能攘已。
vue的單文件組件使得寫組件成本更高一些炮赦,但是思想是類似的,該拆分的還是應該拆分样勃,以獲得更好的復用性吠勘、可讀性、可維護性峡眶。
我們項目中的組件是這樣的:
一個組件的模板好幾屏的html剧防,這樣的組件很多。其實這段邏輯和上面的那個是一樣的幌陕,同樣的if else诵姜,但是這個卻不能一眼看清主體邏輯是什么。打著組件化的幌子搏熄,做著非組件化的事情,這和之前以頁面為開發(fā)單位的時代沒多大區(qū)別暇赤。
我的建議就是更細粒度的拆分組件心例,不管是react還是vue,每個組件可以只有模板和參數(shù)鞋囊,最好是函數(shù)式組件止后,最終的目的是使得組件的層次和邏輯層次一眼就能看清,不需要看半天才看明白結構。
8.模塊译株、類瓜喇、對象、方法歉糜、函數(shù)乘寒,每個代碼單元都加上注釋
理論上來說,寫的好的代碼是自我解釋性很強的匪补,很快就能看清代碼的思路伞辛,這樣的代碼是不需要注釋的。但是夯缺,程序員的水平參差不齊蚤氏,不能保證每個人寫的代碼都能達到很強的自我解釋性,而很多人都不會寫注釋踊兜,這樣別人閱讀他寫的代碼就會很痛苦竿滨。
代碼是有組織的,并且每一個粒度都可以做單元測試捏境,每一個單元都應該有注釋于游,解釋輸入輸出和功能,這個單元包括模塊級別典蝌、類和對象的級別曙砂、方法函數(shù)級別。
我們項目中的代碼注釋很少骏掀,比如:
看這樣一段代碼鸠澈,你需要看懂每一句代碼的意思才能知道每一個方法的意思,看的很是費勁截驮。
但是如果每個函數(shù)加上一個注釋笑陈,
我甚至不需要看這個函數(shù)具體是怎么封裝的,我只要看明白這個函數(shù)的功能還有輸入輸出就夠了葵袭。 就像我們用一個庫涵妥,難道你還要去看懂每一個api是怎么實現(xiàn)的么,不需要坡锡,看懂每一個方法的說明就可以了蓬网。
我們自己寫的代碼也是這樣,每一個函數(shù)都是一個單元鹉勒,都應該像給文章起標題那樣起個名字寫個注釋帆锋,最好也解釋下輸入輸出。類和對象還有模塊也是同樣的禽额。
相信這樣的代碼锯厢,就算代碼寫的不是很優(yōu)雅皮官,閱讀代碼的人都起來也不會那么的費力。
總結
總結一下实辑,我列了8點:
- 所有的資源依賴用絕對路徑
- 使用action creator抽離組件構造action的代碼
- mock data使用mockjs的模板語法和隨機api捺氢,并且加上接口文檔鏈接
- 減少無用的Promise包裝
- 正確理解components、utils剪撬、common的不同
- 引入 lodash作為工具庫
- 組件封裝的粒度更細一些摄乒,使得一眼能看清組件層次
- 模塊、類婿奔、對象缺狠、方法、函數(shù)萍摊,每個代碼單元都加上注釋
以上這些建議都是不涉及到很大的代碼改動的挤茄,還有一些涉及到文件結構和代碼內容比較大調整的,我沒有列在里面冰木。
可以優(yōu)化的點有很多穷劈,寫代碼就像織毛衣,是可以用很多種方式踊沸,織出很多花的歇终。