3.1 组件化方案不彻底之处和JLRoute的缺陷
通过第二部分的讲述,我们的组件化工作差不多完成了80%,但是我们依然发现,组件化并不够彻底。
先来看服务调用方面,我们需要对外提供OpenServiceImpl的头文件,外部模块仍然保持着对业务组件的强依赖,OpenServiceImpl的不兼容变化必然导致所有调用部分的更改,我们期望的黑盒服务便无法实现。如果所有类别的服务接口都在OpenServiceImpl中实现,OpenServiceImpl中的代码会越来越多,难以维护和管理。 另外Protocol文件和OpenServiceImpl的头文件都需要对外披露,如果放到组件实现中,两个组件相互之间有调用,就会导致Podspec的相互循环依赖。
再看URL导航方面,在我们的项目中,我们在ViewController的类别中通过load方法注册URL-Block,这样能够解决JLRoute的中心化注册问题,但是JLRoute仍然存在其他一些缺陷。JLRoute去中心化的具体使用方式如下:
- (void)load
{
@autoreleasepool {
[JLRoutes addRoute:@“/xxxx” handler:^BOOL(NSDictionary *parameters) {
UIViewController *baseViewController = parameters[kLDRouteViewControllerKey];
if (!baseViewController) {
baseViewController = [UIViewController topmostViewController];
}
if (!baseViewController) {
return YES;
}
XXXXViewController *viewController = [[XXXXViewController alloc] init];
if ([baseViewController isKindOfClass:[UINavigationController class]]) {
[(UINavigationController*)baseViewController pushViewController:viewController animated:YES];
}else if (baseViewController.navigationController) {
[baseViewController.navigationController pushViewController:viewController animated:YES];
} else {
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
[baseViewController presentViewController:navController animated:YES completion:NULL];
}
return YES;
}];
}
}
如上所用,JLRoute的缺陷如下:
-
url短链分布式注册时,导航代码的重复拷贝;
-
无法通过URL返回一个controller实例;(TabController也就无法从独立业务组件中不引用Controller头文件获取Controller实例完成设置)
-
class的load方法完成注册,太多对启动时Main线程有影响;
-
同一个url短链的导航方式单一固定,依赖注册
-
单一业务组件中可导航URL分散,无法统一查看;
-
Debug阶段url传递参数错误、not found没有提示;
3.2 LDBusMediator总体方案
针对组件化不彻底的实际问题,结合之前手淘分享的总线架构以及蘑菇街的组件化分享博客,我们完成了一个通用的LDBusMediator中间件帮助我们彻底完成组件化。
LDBusMediator开源Git地址:
我们先来看总体的组件化方案:所有的业务组件通过Connector连接到总线中,Connector需要遵循Connector Protocol方可接入。Connector协议规定了URL导航接入和服务接入的协议,Connector通过Class的Load方法将自己的实例注册到中间件的Cache数组中,方便其他组件在调用时中间件可以通过服务发现的方式进行URL导航和服务调用。(具体见如下的图示)
@implementation Connector_A
#pragma mark - register connector
/**
-
每个组件的实现必须自己通过load完成挂载;
-
load只需要在挂载connector的时候完成当前connecotor的初始化,挂载量、挂载消耗、挂载所耗内存都在可控范围内;
*/
+(void)load{
@autoreleasepool{
[LDBusMediator registerConnector:[self sharedConnector]];
}
}
@end
3.3 LDBusMediator-URL导航方案
URL导航的总线中间件方案很简单,只需要在Connector中实现URL导航接入的接口即可,如图所示:
LDBusMediator-URL导航.png
具体使用如下:
@protocol LDBusConnectorPrt
-(BOOL)canOpenURL:(nonnull NSURL *)URL;
- (nullable UIViewController *)connectToOpenURL:(nonnull NSURL *)URL params:(nullable NSDictionary *)params;
@end
@implementation Connector_A
#pragma mark - LDBusConnectorPrt
/**
-
(1)当调用方需要通过判断URL是否可导航显示界面的时候,告诉调用方该组件实现是否可导航URL;可导航,返回YES,否则返回NO;
-
(2)这个方法跟connectToOpenURL:params配套实现;如果不实现,则调用方无法判断某个URL是否可导航;
*/
-(BOOL)canOpenURL:(nonnull NSURL *)URL{
if ([URL.host isEqualToString:@“ADetail”]) {
return YES;
}
return NO;
}
@end
/**
-
(1)通过connector向busMediator挂载可导航的URL,具体解析URL的host还是path,由connector自行决定;
-
(2)如果URL在本业务组件可导航,则从params获取参数,实例化对应的viewController进行返回;如果参数错误,则返回一个错误提示的[UIViewController paramsError]; 如果不需要中间件进行present展示,则返回一个[UIViewController notURLController],表示当前可处理;如果无法处理,返回nil,交由其他组件处理;
-
(3)需要在connector中对参数进行验证,不同的参数调用生成不同的ViewController实例;也可以通过参数决定是否自行展示,如果自行展示,则用户定义的展示方式无效;
-
(4)如果挂接的url较多,这里的代码比较长,可以将处理方法分发到当前connector的category中;
*/
- (nullable UIViewController *)connectToOpenURL:(nonnull NSURL *)URL params:(nullable NSDictionary *)params{
//处理scheme://ADetail的方式
// tip: url较少的时候可以通过if-else去处理,如果url较多,可以自己维护一个url和ViewController的map,加快遍历查找,生成viewController;
if ([URL.host isEqualToString:@“ADetail”]) {
DemoModuleADetailViewController *viewController = [[DemoModuleADetailViewController alloc] init];
if (params[@“key”] != nil) {
viewController.valueLabel.text = params[@“key”];
} else if(params[@“image”]) {
id imageObj = params[@“image”];
if (imageObj && [imageObj isKindOfClass:[UIImage class]]) {
viewController.valueLabel.text = @“this is image”;
viewController.imageView.image = params[@“image”];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:viewController animated:YES completion:nil];
return [UIViewController notURLController];
} else {
viewController.valueLabel.text = @“no image”;
viewController.imageView.image = [UIImage imageNamed:@“noImage”];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:viewController animated:YES completion:nil];
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
最后
其实前端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)
《前端开发四大模块核心知识笔记》
最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)
《前端开发四大模块核心知识笔记》
最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。