在使用原生與h5頁面進(jìn)行交互的時(shí)候业稼,會建立通道雙方互傳消息,但除了消息通道外蚂蕴,有時(shí)候還會在url后面拼接參數(shù)區(qū)分不同的業(yè)務(wù)場景低散,交互的方式不是那么單一俯邓,具體可能會有:
- 通過消息通道 h5 to app 或 app to h5 ,這時(shí)一般會傳一個(gè)消息熔号,包含有業(yè)務(wù)意義的事件名稱eventName和相關(guān)的數(shù)data稽鞭。
- h5要求app open 一個(gè)新頁面并通過url 后面拼接相關(guān)參數(shù),來傳遞信息引镊。
- h5要求app在本頁面加載到一個(gè)新頁面朦蕴,并通過url后面拼接參數(shù),來傳遞信息弟头。
同時(shí)由于業(yè)務(wù)需要吩抓,存在多個(gè)h5頁面,并且每個(gè)頁面都有不同的事件event亮瓷。
比較簡單的處理方式:
- 搭建h5 - native消息通道
- 處理好本頁面跳轉(zhuǎn)琴拧,還是打開一個(gè)新頁面的邏輯。
- 把全部的event寫到一起嘱支,通過if-else 進(jìn)行判斷處理,如果存在同名event挣饥,那么與url + event一起判斷確定唯一性除师。
這樣無疑是比較簡單和便捷的處理方式,但這其實(shí)并不是真正便捷的方式扔枫。隨著業(yè)務(wù)的迭代汛聚,每個(gè)頁面會增加新的業(yè)務(wù),同時(shí)頁面也會增加短荐,此時(shí)把event都堆積在一起倚舀,導(dǎo)致代碼臃腫、閱讀性降低忍宋,并且會加大了出錯(cuò)的概率痕貌,降低了可維護(hù)性。
為了解決這個(gè)問題糠排,必須要構(gòu)建一個(gè)與h5 - native交互模式匹配的交互方案舵稠,對代碼進(jìn)行解耦,并要求在迭代的過程中入宦,不提高其維護(hù)成本哺徊。
這個(gè)方案的大概思路如下:
- 有多一個(gè)頁面,對應(yīng)應(yīng)該有多個(gè)實(shí)體乾闰,每個(gè)實(shí)體對應(yīng)這個(gè)頁面的業(yè)務(wù)落追。
- 每個(gè)實(shí)體在前臺的時(shí)候能接受和響應(yīng)event。
- 當(dāng)頁面切換的時(shí)候切換對應(yīng)的實(shí)體涯肩。
- 增加一個(gè)新的頁面轿钠,那么就通過增加一個(gè)新的實(shí)體來匹配巢钓。這個(gè)過程中,不需要修改任何邏輯谣膳。實(shí)現(xiàn)OCP竿报。
交互圖:
-
事件交互流程
a.png -
變更頁面,切換
b.png -
擴(kuò)展多個(gè)頁面的邏輯
c.png
通過webViewProcess 完成事件的轉(zhuǎn)發(fā)继谚,完成eventDelegate的切換烈菌。
使用原型模式思想,創(chuàng)建一個(gè)新的delegate類是花履,要實(shí)現(xiàn)相關(guān)協(xié)議芽世,并把元類對象注冊到builder單例中,用于后面根據(jù)url匹配創(chuàng)建诡壁。
APIWebEventDelegateProtocol
@protocol APIWebEventDelegateProtocol <NSObject>
@optional
/*native to h5 event; can be register notifiction*/
- (void)webEventSetupAction;
/*do somthing like native to h5 when webView perload*/
- (void)webPerLoadAction;
/*revice from h5 ,native respod*/
- (void)receiveWebMsg:(NSDictionary *)msg;
/*if respond wiht url*/
- (APIWebEventDelegateRespondType)respodWithUrl:(NSString*)url;
/*handle with url*/
- (void)handleWithUrl:(NSString*)url;
@end
@implementation APICameraWebEventDelegate
#pragma mark -
+ (void)load
{
//注冊
[[APIWebDelegateBuilder shareInstance]registerWithClass:self.class];
}
...
@end
APIWebDelegateBuilder
@interface APIWebDelegateBuilder : NSObject
+ (instancetype)shareInstance;
- (void)registerWithClass:(Class)class;
///生成合適的webDelegate
- (nullable id)webDelegateWithUrl:(NSString *)url param:(NSDictionary *)param;
@end