日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

单文件组件的组件传值_移动端组件化架构(下)

發布時間:2023/12/4 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 单文件组件的组件传值_移动端组件化架构(下) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我的組件化方案

? ? 對于項目架構來說,一定要建立于業務之上來設計架構。不同的項目業務不同,組件化方案的設計也會不同,應該設計最適合公司業務的架構。

架構設計

? ? 以我之前公司項目為例,項目是一個地圖導航應用,業務層之下的核心模塊和基礎模塊占比較大,涉及到地圖SDK、算路、語音等模塊。且基礎模塊相對比較獨立,對外提供了很多調用接口。由此可以看出,公司項目是一個重邏輯的項目,不像電商等App偏展示。

? ? 項目整體的架構設計是:層級架構+組件化架構,對于具體的實現細節會在下面詳細講解。采取這種結構混合的方式進行整體架構,對于組件的管理和層級劃分比較有利,符合公司業務需求。

? ? 在設計架構時,我們將整個項目都拆分為組件,組件化程度相當高。用到哪個組件就在工程中通過Podfile進行集成,并通過URLRouter統一所有組件間的通信。

? ?組件化架構是項目的整體框架,而對于框架中每個業務模塊的實現,可以是任意方式的架構,MVVM、MVC、MVCS等都是可以的,只要通過MGJRouter將組件間的通信方式統一即可。

分層架構

? ? 組件化架構在物理結構上來說是不分層次的,只有組件與組件之間的劃分關系。但是在組件化架構的基礎上,應該根據項目和業務設計自己的層次架構,這套層次架構可以用來區分組件所處的層次及職責,所以我們設計了層級架構+組件化架構的整體架構。

? ? 我公司項目最開始設計的是三層架構:業務層 -> 核心層 (high?+?low) -> 基礎層,其中核心層又分為high和low兩部分。但是這種架構會造成核心層過重,基礎層過輕的問題,這種并不適合組件化架構。

? ? 在三層架構中會發現,low層并沒有耦合業務邏輯,在同層級中是比較獨立的,職責較為單一和基礎。我們對low層下沉到基礎層中,并和基礎層進行合并。所以架構被重新分為三層架構:業務層 -> 核心層 -> 基礎層。之前基礎層大多是資源文件和配置文件,在項目中存在感并不高。

? ? 在分層架構中,需要注意只能上層對下層依賴,下層對上層不能有依賴,下層中不要包含上層業務邏輯。對于項目中存在的公共資源和代碼,應該將其下沉到下層中。

職責劃分

? ? 在三層架構中,業務層負責處理上層業務,將不同業務劃分到相應組件中,例如IM組件、導航組件、用戶組件等。業務層的組件間關系比較復雜,會涉及到組件間業務的通信,以及業務層組件對下層組件的引用。

? ? 核心層位于業務層下方,為業務層提供業務支持,如網絡、語音識別等組件應該劃分到核心層。核心層應該盡量減少組件間的依賴,將依賴降到最小。核心層有時相互之間也需要支持,例如經緯度組件需要網絡組件提供網絡請求的支持,這種是不可避免的。

? ? 其他比較基礎的模塊,都放在基礎層當做基礎組件。例如AFN、地圖SDK、加密算法等,這些組件都比較獨立且不摻雜任何業務邏輯,職責更加單一,相對于核心層更底層??梢园谌綆?、資源文件、配置文件、基礎庫等幾大類,基礎層組件相互之間不應該產生任何依賴。

? ? 在設計各個組件時,應該遵循“高內聚,低耦合”的設計規范,組件的調用應該簡單且直接,減少調用方的其他處理。對于核心層和基礎層的劃分,可以以是否涉及業務、是否涉及同級組件間通信、是否經常改動為參照點。如果符合這幾點則放在核心層,如果不符合則放在基礎層。

集成方式

? ? 新建一個項目后,首先將配置文件、URLRouter、App容器等集成到主工程中,做一些基礎的項目配置,隨后集成需要的組件即可。項目被整體拆分為組件化架構后,應用對所有組件的集成方式都是一樣的,通過Podfile將需要的組件集成到項目中。通過組件化的方式,使得開發新項目速度變得非常快。

? ? 在集成業務層和核心層組件后,組件間的通信都是由URLRouter進行通信,項目中不允許直接依賴組件源碼。而基礎層組件則在集成后直接依賴,例如資源文件和配置文件,這些都是直接在主工程或組件中使用的。第三方庫則是通過核心層的業務封裝,封裝后由URLRouter進行通信,但核心層也是直接依賴第三方庫源碼的。

? ? 組件的集成方式有兩種,源碼和framework的形式,我們使用framework的方式集成。因為一般都是項目比較大才用組件化的,但大型項目都會存在編譯時間的問題,如果通過framework則會大大減少編譯時間,可以節省開發人員的時間。

組件間通信

? ? 對于組件間通信,我們采用的MGJRouter方案。因為MGJRouter現在已經很穩定了,而且可以滿足蘑菇街這樣量級的App需求,證明是很好的,沒必要自己寫一套再慢慢踩坑。

? ? MGJRouter的好處在于,其調用方式很靈活,通過MGJRouter注冊并在block中處理回調,通過URL直接調用或者URL+Params字典的方式進行調用。由于通過URL拼接參數或Params字典傳值,所以其參數類型沒有數量限定,傳遞比較靈活。在通過openURL:調用后,可以在completionBlock中處理完成邏輯。

? ? MGJRouter有個問題在于,在編寫組件間通信的代碼時,會涉及到大量的Hardcood。對于Hardcode的問題,蘑菇街開發了一套后臺系統,將所有的Router需要的URL和參數名,都定義到這套系統中。我們維護了一個Plist表,內部按不同組件進行劃分,包含URL和傳參名以及回調參數。

小思考

? ? MGJRouter可以在openURL:時傳入一個NSDictionary參數,在接觸RAC之后,我在想是不是可以把NSDictionary參數變為RACSignal參數,直接傳一個信號過去。

? ? 注冊MGJRouter:

objc
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
????[subscriber sendNext:@"劉小壯"];
????return [RACDisposable disposableWithBlock:^{
????????NSLog(@"disposable");
????}];
}];
[MGJRouter registerURLPattern:@"CTB://UserCenter/getUserInfo" withSignal:signal];

? ? 調用MGJRouter:

objc
RACSignal *signal = [MGJRouter openURL:@"CTB://UserCenter/getUserInfo"];
[signal subscribeNext:^(NSString *userName) {
????NSLog(@"userName %@", userName);
}];

? ? 這種方式是可行的。使用RACSignal方式優點在于,相對于直接傳字典過去更加靈活,并且具備RAC的諸多特性。但缺點也不少,信號控制不好亂用的話也很容易挖坑,是否使用還是看團隊情況了。

H5和Native通信

? ? 在項目中經常會用到H5頁面,如果能通過點擊H5頁面調起原生頁面,這樣的話Native和H5的融合會更好。所以我們設計了一套H5和Native交互的方案,這套方案可以使用URLRouter的方式調起原生頁面,實現方式也很簡單,并且這套方案和H5原本的跳轉邏輯并不沖突。

? ? 通過iOS自帶UIWebView創建一個H5頁面后,H5可以通過調用下面的JS函數和Native通信。調用時可以傳入新的URL,這個URL可以設置為URLRouter的URL。

objc
window.location.href = 'CTB://UserCenter/UserLogin?userName=lxz&WeChatID=lz2046703959';

? ? 通過JS刷新H5頁面時,會調用下面的代理方法。如果方法返回YES,則會根據URL協議進行跳轉。

objc
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;

? ? 跳轉時系統會判斷通信協議,如果是HTTP等標準協議,則會在當前頁面進行刷新。如果跳轉協議在URL Schame中注冊,則會通過系統openURL:的方式調用到AppDelegate的系統代理方法中,在代理方法中調用URLRouter,則可以通過H5頁面喚起原生頁面。

APP Service

? ? 在應用啟動過程中,通常會做一些初始化操作。有些初始化操作是運行程序所需要的,例如崩潰統計、建立服務器的長連接等?;蛴械慕M件會對初始化操作有依賴關系,例如網絡組件依賴requestToken等。

? ? 對于應用啟動時的初始化操作,應該創建一個AppService來統一管理啟動操作,將初始化操作都放在里面,包含創建根控制器等。其中有的初始化操作需要盡快執行,有的并不需要立即執行,可以根據不同操作設定優先級,來管理所有初始化操作。

objc
#import
typedef NS_ENUM(NSUInteger, CTBAppServicePriority) {
????CTBAppServicePriorityLow,
????CTBAppServicePriorityDefault,
????CTBAppServicePriorityHigh,
};
@interface CTBAppService : NSObject
+ (instancetype)appService;
- (void)registerService:(dispatch_block_t)serviceBlock?
???????????????priority:(CTBAppServicePriority)priority;
@end

參數傳遞

項目中存在很多的模型定義,那組件化后這些模型應該定義在哪呢?

? ? casatwy對模型類的觀點是去Model化,簡單來說就是用字典代替Model存儲數據。這對于組件化架構來說,是解決組件之間數據傳遞的一個很好的方法。但是去Model的方式,會存在大量的字段讀取代碼,使用起來遠沒有模型類方便。

? ? 因為模型類是關乎業務的,理論上必須放在業務層也就是業務組件這一層。但是要把模型對象從一個組件中當做參數傳遞到另一個組件中,模型類放在調用方和被調方的哪個組件都不太合適,而且有可能不只兩個組件使用到這個模型對象。這樣的話在其他組件使用模型對象,必然會造成引用和耦合。

? ? 如果在用到這個模型對象的所有組件中,都分別維護一份相同的模型類,或者各自維護不同結構的模型類,這樣之后業務發生改變模型類就會很麻煩,這是不可取的。

設計方案

如果將所有模型類單獨拉出來,定義一個模型組件呢?

? ? 這個看起來比較可行,將這個定義模型的組件下沉到基礎層,模型組件不包含業務,只聲明模型對象的類。如果將原來各個組件的模型類定義都拉出來,單獨放在一個組件中,可以將原有各組件的Model層變得很輕量,這樣對整個項目架構來說也是有好處的。

? ? 在通過Router進行組件間調用時,通過字典進行傳值,這種方式比較靈活。在組件內部使用Model層時,還是用模型組件中定義的Model類。Model層建議還是用Model對象的形式比較方便,不建議整體使用去Model化的設計。在接收到其他組件傳遞過來的字典參數時,可以通過Model類提供的初始化方法,或其他轉Model框架將字典轉為Model對象。

objc
@interface CTBStoreWelfareListModel : NSObject
/**
?* 自定義初始化方法
?*/
- (instancetype)initWithDict:(NSDictionary *)dict;
@end

? ? 我公司持久化方案用的是CoreData,所有模型的定義都在CoreData組件中,則不需要再單獨創建一個模型組件。

動態化構想

? ? 我公司項目是一個常規的地圖類項目,首頁和百度、高德等主流地圖導航App一樣,有很多添加在地圖上的控件。有的版本會添加控件上去,而有的版本會刪除控件,與之對應的功能也會被隱藏。

? ? 所以,有次和組里小伙伴們開會的時候就在考慮,能不能在服務器下發代碼對首頁進行布局!這樣就可以對首頁進行動態布局,例如有活動的時候在指定時間顯示某個控件,這樣可以避免App Store審核慢的問題。又或者線上某個模塊出現問題,可以緊急下架出問題的模塊。

? ?對于這個問題,我們設計了一套動態配置方案,這套方案可以對整個App進行配置。

配置表設計

? ? 對于動態配置的問題,我們簡單設計了一個配置表,初期打算在首頁上先進行試水,以后可能會布置到更多的頁面上。這樣應用程序各模塊的入口,都可以通過配置表來控制,并且通過Router控制頁面間跳轉,靈活性非常大。

? ? 在第一次安裝程序時使用內置的配置表,之后每次都用服務器來替換本地的配置表,這樣就可以實現動態配置應用。下面是一個簡單設計的配置數據,JSON中配置的是首頁的配置信息,用來模擬服務器下發的數據,真正服務器下發的字段會比這個多很多。

objc
{
????"status": 200,
????"viewList": [
????????{
????????????"className": "UIButton",
????????????"frame": {
????????????????"originX": 10,
????????????????"originY": 10,
????????????????"sizeWidth": 50,
????????????????"sizeHeight": 30
????????????},
????????????"normalImageURL": "http://image/normal.com",
????????????"highlightedImageURL": "http://image/highlighted.com",
????????????"normalText": "text",
????????????"textColor": "#FFFFFF",
????????????"routerURL": "CTB://search/***"
????????}
????]
}

? ? 對于服務器返回的數據,我們會創建一套解析器,這個解析器用來將JSON解析并“轉換”為標準的UIKit控件。點擊后的事件都通過Router進行跳轉,所以首頁的靈活性和Router的使用程度成正比。

? ? 這套方案類似于React Native的方案,從服務器下發頁面展示效果,但沒有React Native功能那么全。相對而言是一個輕量級的配置方案,主要用于頁面配置。

資源動態配置

? ? 除了頁面的配置之外,我們發現地圖類App一般都存在ipa過大的問題,這樣在下載時很消耗流量以及時間。所以我們就在想能不能把資源也做到動態配置,在用戶運行程序的時候再加載資源文件包。

? ? 我們想通過配置表的方式,將圖片資源文件都放到服務器上,圖片的URL也隨配置表一起從服務器獲取。在使用時請求圖片并緩存到本地,成為真正的網絡APP。在此基礎上設計緩存機制,定期清理本地的圖片緩存,減少用戶磁盤占用。

淘寶組件化架構

本章節源自于宗心在阿里技術沙龍上的一次技術分享。

(https://yq.aliyun.com/articles/129)

架構發展

? ? 淘寶iOS客戶端初期是單工程的普通項目,但隨著業務的飛速發展,現有架構并不能承載越來越多的業務需求,導致代碼間耦合很嚴重。后期開發團隊對其不斷進行重構,將項目重構為組件化架構,淘寶iOS和Android兩個平臺,除了某個平臺特有的一些特性或某些方案不便實施之外,大體架構都是差不多的。

發展歷程

  • 剛開始是普通的單工程項目,以傳統的MVC架構進行開發。隨著業務不斷的增加,導致項目非常臃腫、耦合嚴重。

  • 2013年淘寶開啟"all in 無線"計劃,計劃將淘寶變為一個大的平臺,將阿里系大多數業務都集成到這個平臺上,造成了業務的大爆發。 淘寶開始實行插件化架構,將每個業務模塊劃分為一個子工程,將組件以framework二方庫的形式集成到主工程。但這種方式并沒有做到真正的拆分,還是在一個工程中使用git進行merge,這樣還會造成合并沖突、不好回退等問題。

  • 迎來淘寶移動端有史以來最大的重構,將其重構為組件化架構。將每個模塊當做一個組件,每個組件都是一個單獨的項目,并且將組件打包成framework。主工程通過podfile集成所有組件的framework,實現業務之間真正的隔離,通過CocoaPods實現組件化架構。

  • 架構優勢

    ? ? 淘寶是使用git來做源碼管理的,在插件化架構時需要盡可能避免merge操作,否則在大團隊中協作成本是很大的。而使用CocoaPods進行組件化開發,則避免了這個問題。

    ? ? 在CocoaPods中可以通過podfile很好的配置各個組件,包括組件的增加和刪除,以及控制某個組件的版本。使用CocoaPods的原因,很大程度是為了解決大型項目中,代碼管理工具merge代碼導致的沖突。并且可以通過配置podfile文件,輕松配置項目。

    ? ? 每個組件工程有兩個target,一個負責編譯當前組件和運行調試,另一個負責打包framework。先在組件工程做測試,測試完成后再集成到主工程中集成測試。

    ? ? 每個組件都是一個獨立app,可以獨立開發、測試,使得業務組件更加獨立,所有組件可以并行開發。下層為上層提供能滿足需求的底層庫,保證上層業務層可以正常開發,并將底層庫封裝成framework集成到主工程中。

    ? ? 使用CocoaPods進行組件集成的好處在于,在集成測試自己組件時,可以直接在本地主工程中,通過podfile使用當前組件源碼,可以直接進行集成測試,不需要提交到服務器倉庫。

    淘寶四層架構

    ? ? 淘寶架構的核心思想是一切皆組件,將工程中所有代碼都抽象為組件。

    ? ? 淘寶架構主要分為四層,最上層是組件Bundle(業務組件),依次往下是容器(核心層),中間件Bundle(功能封裝),基礎庫Bundle(底層庫)。容器層為整個架構的核心,負責組件間的調度和消息派發。

    總線設計

    ? ? 總線設計:URL路由+服務+消息。統一所有組件的通信標準,各個業務間通過總線進行通信。

    URL總線

    ? ? 通過URL總線對三端進行了統一,一個URL可以調起iOS、Android、前端三個平臺,產品運營和服務器只需要下發一套URL即可調用對應的組件。

    ? ? URL路由可以發起請求也可以接受返回值,和MGJRouter差不多。URL路由請求可以被解析就直接拿來使用,如果不能被解析就跳轉H5頁面。這樣就完成了一個對不存在組件調用的兼容,使用戶手中比較老的版本依然可以顯示新的組件。

    ? ? 服務提供一些公共服務,由服務方組件負責實現,通過Protocol進行調用。

    消息總線

    ? ? 應用通過消息總線進行事件的中心分發,類似于iOS的通知機制。例如客戶端前后臺切換,則可以通過消息總線分發到接收消息的組件。因為通過URLRouter只是一對一的進行消息派發和調度,如果多次注冊同一個URL,則會被覆蓋掉。

    Bundle App

    ? ? 在組件化架構的基礎上,淘寶提出Bundle App的概念,可以通過已有組件,進行簡單配置后就可以組成一個新的app出來。解決了多個應用業務復用的問題,防止重復開發同一業務或功能。

    ? ? ?Bundle即App,容器即OS,所有Bundle App被集成到OS上,使每個組件的開發就像app開發一樣簡單。這樣就做到了從巨型app回歸普通app的輕盈,使大型項目的開發問題徹底得到了解決。

    總? ?結

    ? ? 好多朋友在看完這篇文章后,都問有沒有Demo。其實架構是思想上的東西,重點還是理解架構思想。文章中對思想的概述已經很全面了,用多個項目的例子來描述組件化架構。就算提供了Demo,也沒法把Demo套在其他工程上用,因為并不一定適合所在的工程。

    ? ? 后來想了一下,我把組件化架構的集成方式,簡單寫了個Demo,這樣可以解決很多人在架構集成上的問題。我把Demo放在我Github上了,用Coding的服務器來模擬我公司私有服務器,直接拿MGJRouter來當Demo工程中的Router。下面是Demo地址。

    https://github.com/DeveloperErenLiu/ComponentArchitecture

    推薦閱讀

    iOS匯編快速入門

    如何評價 SwiftUI?

    從 SwiftUI 談聲明式 UI 與類型系統

    在看就點點吧?

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的单文件组件的组件传值_移动端组件化架构(下)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。