摘要:在里,通過的服務(wù)和依賴注入可以很輕松的實現(xiàn),這里是我集中功能的服務(wù)文件文件功能類集合獲取短信驗證碼這些功能需要用到的方法需要的地方只要注入這個服務(wù)就可以獲取想要的功能。寫成組件會有樣式的限制,而這樣寫沒有。
最近開始維護(hù)項目,然后我發(fā)現(xiàn)每天的時間常常是花在修改幾個小功能上,改了問題有出了另一個問題,思考哪里不對?,然后這么一天就過去了。。然后我就開始思考標(biāo)題好讓我的時間不總是花在修改上,下面的是我最近的一些總結(jié)。
功能分離這個算是面向?qū)ο罄锏乃枷?,在組件里,有很多功能是獨立的,比如最常見的發(fā)送驗證碼,確認(rèn)密碼等。把這些邏輯封裝成一個或幾個函數(shù)寫在組件里的話,這在組件很小的時候沒有什么影響,但是當(dāng)組件功能比較復(fù)雜的時候,就會有些問題:
組件邏輯區(qū)域會變的很大,各種方法混雜很難一眼辨識
因為定義功能需要的變量和方法不在一起,導(dǎo)致修改麻煩
功能分離就是把這些功能抽離出來,寫出一個類,然后在組件里引入。
下面是一個簡單的彈窗控制的功能的類和這個類的使用:
export class DialogCtrl { isVisible = false; open () { this.isVisible = true; } close () { this.isVisible = false; } }
然后在需要的組件里引入并實例化:
DialogCtrl = new this.CommonService.DialogCtrl(); // 是否打開彈窗
在html里可以直接這樣用:
這個nz-modal是一個彈窗,在組件里我們只有一個變量的聲明,如此簡潔!而在html里DialogCtrl.isVisible,DialogCtrl.close()的形式也很容易理解它的作用和出處。
這樣做的另一個好處是利于實現(xiàn)復(fù)用。對于可以復(fù)用的功能,比如上面發(fā)送驗證碼的邏輯,可以建一個全局的服務(wù)來提供。在angular里,通過angular的服務(wù)和依賴注入可以很輕松的實現(xiàn),這里是我集中功能的common.service.ts服務(wù)文件:
common.servide.ts文件:
@Injectable() export class CommonService { // 功能類集合 public DialogCtrl = DialogCtrl; public MessageCodeCtrl = MessageCodeCtrl; public CheckPasswordCtrl = CheckPasswordCtrl; constructor( private http: HttpClient ) { } /* 獲取短信驗證碼(這些功能需要用到的方法) -------------------------- */ public getVerificationCode (phoneNum: string): Observable{ return this.http.get("/account/short_message?phoneNumber=" + phoneNum); } }
需要的地方只要注入這個服務(wù)就可以獲取想要的功能。相比較直接建立一個組件來實現(xiàn),我覺得這樣寫有一些優(yōu)勢:
靈活性更高。寫成組件會有樣式的限制,而這樣寫沒有。
更簡潔。寫成組件,與之溝通只能通過子父組件的傳入變量,監(jiān)聽子組件事件的方法,你使用的組件不可避免的會多出這些變量和方法。
狀態(tài)管理不知道大伙兒有沒有這樣的感覺,自己寫新項目的時候覺得邏輯清晰,代碼簡練,功能也都實現(xiàn)了,但是過一段時間去看或者要改自己的代碼的時候...哇,看不懂。
前端復(fù)雜的地方源于數(shù)不清的狀態(tài),于是我為那些有復(fù)雜狀態(tài)的組件建立一個集中管理狀態(tài)的對象(這里我取名為Impure):
/* 變量定義 -- 狀態(tài) -------------------------- */ registerForm: FormGroup; // 注冊賬號表單 registerInfoForm: FormGroup; // 公司信息表單 isSubmitting = false; // 表單是否正在提交 nowForm = "registerForm"; // 當(dāng)前正在操作的表單 MessageCodeCtrl = new this.CommonService.MessageCodeCtrl(this.Msg, this.CommonService); // 驗證碼控制 /* 變量定義 -- 定值 -------------------------- */ registerFormSubmitAttr = ["login", "password", "shortMessageCode", "roles", "langKey"]; registerInfoFormFormSubmitAttr = ["simName", "contacter", "officeTel", "uid"]; /* 改變狀態(tài)事件 -------------------------- */ Impure = { // 表單初始化 RegisterFormInit: () => this.registerForm = this.registerFormInit(), RegisterInfoFormInit: () => this.registerInfoForm = this.registerInfoFormInit(), // 驗證碼不合法 MessageCodeInvalid: { notSend: () => this.Msg.error("您還未發(fā)送驗證碼"), notRight: () => this.Msg.error("驗證碼錯誤") }, // 表單提交 FormSubmit: { invalid: () => this.Msg.error("表單填寫有誤"), before: () => this.isSubmitting = true, registerOk: () => { this.Msg.success("賬號注冊成功"); this.nowForm = "registerInfoForm"; }, registerInfoOk: () => { this.Msg.success("保存信息成功!請耐心等待管理員審核"); this.Router.navigate(["/login"]); }, fail: () => this.Msg.error("提交失敗,請重試"), after: () => this.isSubmitting = false } };
這是一個簡單的有兩個表單的注冊組件,因為兩個表單html耦合度很高,所以寫在了一起。
在組件內(nèi)將變量分為狀態(tài)和定值的兩類,聲明了一個Impure對象來集中管理這些狀態(tài),原則上這個組件里所有狀態(tài)的改變都寫在Impure里,而將事件觸發(fā)的判斷條件,數(shù)據(jù)處理寫在Impure外面。
可以對比下這兩個使用Impure和不使用Impure的表單提交方法:
/* 注冊賬號表單提交(Impure) -------------------------- */ async register (form) { const _ = this.Fp._; // ramda庫,用于數(shù)據(jù)處理 const { MessageCodeInvalid, FormSubmit } = this.Impure; // 表單不合法 if (form.invalid) { FormSubmit.invalid(); return; } // 驗證碼不合法 if (!this.MessageCodeCtrl.code) { MessageCodeInvalid.notSend(); return; } if (this.MessageCodeCtrl.code !== form.controls.shortMessageCode.value) { MessageCodeInvalid.notRight(); return; } // 表單提交 FormSubmit.before(); const data = _.compose(_.pick(this.registerFormSubmitAttr), _.map(_.prop("value")))(form.controls); // 數(shù)據(jù)處理 const res = await this.AccountService.producerRegisterFirst(data).toPromise(); if (!res) { FormSubmit.registerOk(); } else { FormSubmit.fail(); } FormSubmit.after(); } /* 公司信息表單提交(非Impure) -------------------------- */ async registerInfo ({ simName, contacter, officeTel }) { // 表單不合法 if (this.registerInfoForm.invalid) { this.Msg.error("表單填寫有誤"); return; } // 表單提交 this.isSubmitting = true; const data = { // 數(shù)據(jù)處理 simName: simName.value, contacter: contacter.value, officeTel: officeTel.value, uid: this.registerForm.controls.phone.value }; const res = await this.AccountService.producerRegisterSecond(data).toPromise(); if (!res) { this.Msg.success("保存信息成功!請耐心等待管理員審核"); this.Router.navigate(["/login"]); } else { this.Msg.error("提交失敗,請重試"); } this.isSubmitting = false; }
使用Impure管理狀態(tài)后,邏輯清晰,在提交表單時你只需要關(guān)注事件發(fā)生的條件就可以了,而第二個條件和狀態(tài)寫在一起會很混亂,不能一眼清楚這個狀態(tài)改變發(fā)生在什么時候,特別是你一段時間再來看的時候。
其實這里的數(shù)據(jù)處理(這里面的data)應(yīng)該多帶帶拿出來寫一個方法的,我只是來頂一下用純函數(shù)來處理數(shù)據(jù)的優(yōu)點,這里的_是用了ramda這個庫。相比較第二個處理方式,第一種方式更加優(yōu)雅,簡潔,很容易看出數(shù)據(jù)的源頭是什么(這里是form.controls),多帶帶抽離成數(shù)據(jù)處理函數(shù)也有很高的復(fù)用性。
假如某一天你要改下這里兩個表格的成功后的狀態(tài),不再需要到這兩個長長的提交函數(shù)里找到它們?nèi)缓笠粋€一個改,只要在Impure里面改就可以了,你甚至不需要看那兩個提交的方法。
這樣子,一個組件可以大致分為狀態(tài),狀態(tài)管理(impure),改變狀態(tài)的事件(狀態(tài)改變的判斷條件),和數(shù)據(jù)處理(純函數(shù))四部分,各司其職,很好維護(hù)。
結(jié)語這些適合我但不一定適合所有人,每個人都有自己的風(fēng)格,各位看官感受下就好。以后我有其它方面的總結(jié)也會拿出來分享。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/88579.html
摘要:高內(nèi)聚低耦合高內(nèi)聚低耦合一直是軟件設(shè)計領(lǐng)域里亙古不變的話題,重構(gòu)的目標(biāo)是提高代碼的內(nèi)聚性,降低各功能間的耦合程度,降低后期維護(hù)成本,特別是寫業(yè)務(wù)代碼,這一點相當(dāng)重要。0x00 前言 我是一名來自螞蟻金服-保險事業(yè)群的前端工程師,在一線大廠的業(yè)務(wù)部門寫代碼,非常辛苦但也非常充實。業(yè)務(wù)代碼不同于框架代碼、個人項目或者開源項目,它的特點在于邏輯復(fù)雜、前后依賴多、可復(fù)用性差、迭代周期短,今天辛辛苦苦...
摘要:發(fā)布按照官方發(fā)布計劃,的發(fā)布意味著進(jìn)入階段,徹底退出舞臺,的還有半年結(jié)束。為了應(yīng)對這個挑戰(zhàn),美團(tuán)點評境外度假前端研發(fā)團(tuán)隊自年月起啟動了面向端用戶的赫爾墨斯項目。前端技術(shù)越來越復(fù)雜,有不低的技術(shù)門檻。 推薦 1. 利用 Dawn 工程化工具實踐 MobX 數(shù)據(jù)流管理方案 https://zhuanlan.zhihu.com/p/... 項目在最初應(yīng)用 MobX 時,對較為復(fù)雜的多人協(xié)作項...
摘要:導(dǎo)讀要從容器化開始,而容器又需要從開始,本文將介紹如何寫出一個優(yōu)雅的文件。只要記住以上三點就能寫出不錯的。執(zhí)行完成項目的構(gòu)建。 導(dǎo)讀 Kubernetes要從容器化開始,而容器又需要從Dockerfile開始,本文將介紹如何寫出一個優(yōu)雅的Dockerfile文件。 文章主要內(nèi)容包括: Docker容器 Dockerfile 使用多階構(gòu)建 感謝公司提供大量機(jī)器資源及時間讓我們可以實踐...
摘要:組合的概念是非常直觀的,并不是函數(shù)式編程獨有的,在我們生活中或者前端開發(fā)中處處可見。其實我們函數(shù)式編程里面的組合也是類似,函數(shù)組合就是一種將已被分解的簡單任務(wù)組織成復(fù)雜的整體過程。在函數(shù)式編程的世界中,有這樣一種很流行的編程風(fēng)格。 JavaScript函數(shù)式編程,真香之認(rèn)識函數(shù)式編程(一) 該系列文章不是針對前端新手,需要有一定的編程經(jīng)驗,而且了解 JavaScript 里面作用域,閉...
閱讀 2727·2023-04-26 02:28
閱讀 2559·2021-09-27 13:36
閱讀 3131·2021-09-03 10:29
閱讀 2760·2021-08-26 14:14
閱讀 2108·2019-08-30 15:56
閱讀 839·2019-08-29 13:46
閱讀 2614·2019-08-29 13:15
閱讀 459·2019-08-29 11:29