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