一、簡述
最近項目組打算引入weex,並選定了一個頁面進行試水。頁面很簡單,主要是獲取數據渲染頁面,並可以跳轉到指定的頁面。跟之前使用RN 相比,weex 確實要簡單很多。從下圖中我們可以看到,weex 頁面需要跳轉到原生頁面,並且跳轉到哪個頁面我們可能並不能寫死。也就是說只要原生頁面之前項目中寫過了,那麼理論上來說使用weex 可以任意調用。那麼問題來了,我原來的頁面可能只知道名字,我怎麼為那個頁面傳值呢?比如有個頁面orderDetailVC ,跳轉時需要傳入orderId,即orderDetailVC.orderId = @"123";
二、思考
可能最直接的想法就是直接原生給weex 提供一個方法,讓weex 傳入orderId,然後再push。但是如果明天我們需要跳轉到另一個頁面merchantDetailVC呢?它需要的不是orderId了,可能是一個merchantId,甚至更多參數。那怎麼才能實現任意跳轉呢?我的想法是,項目是我寫的,需要跳轉到哪個類,那麼這個類名我肯定是清楚的,並且這個類應該需要什麼參數我也是清楚的。只不過我可能不知道怎麼用weex 把它參數傳過去而已。如果知道了類名就意味著我知道了這個類,我能找到這個類,那麼我就知道這個類有哪些屬性了,這個類的所有屬性我都能拿到,只不過有些是我需要給它賦值的,有些是不需要處理的。
三、實現
整體的思路是:原生給weex 提供一個通用的跳轉方法。參數是類名和屬性字典。
//控制器相關 /* vcName: 頁面名稱 param:頁面所需參數(如原來的頁面需要傳遞小區id,工單號等等,字典形式傳過去,key 與頁面所需參數名稱一致即可。 */ -(void)pushViewController:(NSString *)vcName param:(NSDictionary *)param; /* 將APP 當前展示的頁面pop */ -(void)popViewController; /* vcName: 頁面名稱 param:頁面所需參數(如原來的頁面需要傳遞小區id,工單號等等,字典形式傳過去,key 與頁面所需參數名稱一致即可。 */ -(void)presentViewController:(NSString *)vcName param:(NSDictionary *)param finish:(WXModuleCallback)callback; /* 將APP 當前展示的頁面dismiss */ -(void)dismissViewController:(WXModuleCallback)callback;
提供方法後weex 可以這樣調用:
確定了方案之後,剩下唯一的事情就是如何實現給weex 提供的方法。代碼如下:
-(void)pushViewController:(NSString *)vcName param:(NSDictionary *)param{ //獲取類 Class vcClass = NSClassFromString(vcName); if (vcClass == nil) { return; } BaseViewController *vc = [[vcClass alloc] init]; vc.hidesBottomBarWhenPushed = YES; //屬性數量 unsigned int count = 0; //獲取屬性列表 objc_property_t *plist = class_copyPropertyList(vcClass, &count); for (int i = 0; i<count; i++) { //取出屬性 objc_property_t property = plist[i]; //取出屬性名稱 NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)]; //以這個屬性名稱作為key ,查看傳入的字典裡是否有這個屬性的value if (param[propertyName]) { [vc setValue:param[propertyName] forKey:propertyName]; } } //釋放 free(plist); //獲取當前頁面控制器 /* 獲取當前頁面控制器是根據響應鏈獲取的。 */ UIViewController *currentVC = [Utils getCurrentVC]; if ([currentVC isKindOfClass:[UINavigationController class]]) { [(UINavigationController *)currentVC pushViewController:vc animated:YES]; }else{ [currentVC.navigationController pushViewController:vc animated:YES]; } }
經過小規模自測發現是可以實現需求的。但是由於實現時間不長,可能會有不足之處,請謹慎參考。