-
Notifications
You must be signed in to change notification settings - Fork 60
4. Component (组件式开发)
使用组件开发已经是软件开发的热门方式,就前端和移动端更以URL路由组件方式更为常见,为了追赶这股技术潮流,乐高在2.0版本开始就开始加入这个概念。但是在乐高中的URL路由组件方式和别的框架有两点不同之处:
- URL路由方式和网址相似(支持网址参数)
- 以组件名的注册方式
- 组件打开方来完成下一个组件切换功能
这样设计是为了完美整合进乐高的模块运行体系,因为乐高1.x版本的模块高度耦合在一在,使用这种简化版的URL路由方式,使模块各自独立,提高了可维护性,注意的是这种设计只为了处理组件(模块组件和控制器组件)切换,不针对URL路由作其它业务处理。简单来说就一句话:功能模块化,界面组件化。
引入组件开发方式,使VIPER模块与普通控制器统一对待,以组件通用API实现对VIPER模块与普通控制器的双向桥接,分为以下功能:
- 统一的URL路由跳转方法
- 强大的轻量级组件事件消息通信
- 内存安全的通知中心注册与接收方式
VIPER模块和控制器要成为组件,必需使用导出宏来指定,使框架来识别它们具有这些功能:事件处理机制、URL路由跳转、组件参数传递、统一的组件生命周期等。那么怎样把它们导出为一个组件?
VIPER模块各层通过继承框架提供的父类层后,会自动转为一个组件。具体点来说是VIPER模块的事件层 XFPresenter 层会充当一个组件类型,因为它实现了 XFModuleComponentRunnable 接口,使当前模块成为可运行组件。
框架提供可使普通控制器导出为组件的能力,具有VIPER模块的一些功能。
- 使用继承方式
#import "XFLegoVIPER.h"
// 继承可运行组件控制器XFComponentViewController
@interface BDJPublishViewController : XFComponentViewController
@end- 使用分类方式
#import "XFLegoVIPER.h"
// 如要当前控制器不是继承的UIViewController类,可实现XFControllerComponentRunnable接口使控制器成为可运行组件
@interface BDJPostPictureBrowseViewController : UIViewController <XFControllerComponentRunnable>
/* ---------------- 可选实现 ---------------- */
// 上一个URL组件传递过来的URL参数
@property (nonatomic, copy) NSDictionary *URLParams;
// 上一个URL组件传递过来的自定义数据对象
@property (nonatomic, copy) id componentData;
// 预设要传递给其它组件的意图数据
@property (nonatomic, copy) id intentData;
@end
@implementation BDJPostPictureBrowseViewController
// 把控制器导出为组件
XF_EXPORT_COMPONENT
@end任何一个可运行组件,都有获取焦点方法和失去焦点方法可以覆盖实现,模块组件可以在事件层Presenter,控制器组件在相应控制器中:
/**
* 组件将获得焦点
*/
- (void)componentWillBecomeFocus;
/**
* 组件将失去焦点
*/
- (void)componentWillResignFocus;这种方式是:URL + 组件名, 即一个组件名对应一个访问的URL。
// 注意组件名首字母要大写
[XFURLRoute register:@"bdj://indexTab" forComponent:@"IndexTab"];
[XFURLRoute register:@"bdj://indexTab/publish" forComponent:@"Publish"];由于URL路径的最后一个路径就是组件名,所有可以使用快速初始化方式:
[XFURLRoute register:@"bdj://indexTab"];
[XFURLRoute register:@"bdj://indexTab/publish"];更快的初始化URL列表:
// 使用自定义类封装起来
@implementation BDJAppURLRegister
+ (void)urlRegister
{
[XFURLRoute initURLGroup:@[
@"bdj://indexTab", // Tab主UI框架页
@"bdj://indexTab/publish", // 发布作品
@"bdj://friendTrends/friendsRecomment", // 推荐朋友
@"bdj://userCenter/signIn", // 登录
@"bdj://essence/recommendTag", // 推荐标签
@"bdj://essence/post/postPictureBrowse", // 浏览大图
@"bdj://essence/post/postComment", // 帖子评论
]];
}
@end这种情况适用于乐高模块间的跳转,也适用于模块到控制器的跳转,下面Push方式:
@implementation BDJPostRouting
// 组装模块
XF_AutoAssemblyModule_Fast
// 跳转组件
- (void)transition2PostComment
{
XF_PUSH_URLComponent_Fast(@"bdj://essence/post/postComment")
}
@end使用Present方式:
@implementation BDJPostRouting
// 组装模块
XF_AutoAssemblyModule_Fast
// 跳转组件
- (void)transition2PostPictureBrowse
{
XF_Present_URLComponent_Fast(@"bdj://essence/post/postPictureBrowse")
}
@end自定义跳转方式:
@implementation BDJIndexTabRouting
// 组装模块
XF_AutoAssemblyModule_Fast
// 跳转组件
- (void)transition2Publish
{
// 自定义跳转 (Publish组件为控制器)
[self.uiBus openURL:@"bdj://indexTab/publish" withTransitionBlock:^(__kindof UIViewController *thisInterface, __kindof UIViewController *nextInterface, TransitionCompletionBlock completionBlock) {
// 使用不带动画的方式
[thisInterface presentViewController:nextInterface animated:NO completion:completionBlock];
} customCode:nil];
}
@end可用于跳转到模块组件或控制器组件,使用的API宏和模块使用的相同:
#import "XFComponentViewController.h" // 导入头文件
// 继承可运行组件控制器XFComponentViewController
@interface BDJPublishViewController : XFComponentViewController
@end
@implementation BDJPublishViewController
- (void)doFunAction:(UIButton *)target
{
// 先显示退出动画
[self cancelWithCompletionBlock:^{
switch (target.tag) {
case BDJPublishTypeWords:
self.intentData = @"控制器到模块的数据";
XF_Present_URLComponent_Fast(@"bdj://indexTab/publish/publishContent")
break;
default:
break;
}
[self dismissViewControllerAnimated:NO completion:nil];
}];
}
@end乐高可以通过组件跟踪引擎,实时检测每一个打开或闭的组件,标识当前正显示的组件,可通过以下方式打开:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// 开启组件追踪log(可选)
[XFComponentManager enableLog];
// 注册APP的所有URL组件
[BDJAppURLRegister urlRegister];
// 根据URL显示组件
XF_ShowURLComponent2Window_Fast(@"bdj://indexTab")
return YES;
}当项目完全以乐高VIPER方式编写时,可以启用URL路径检测功能,内部会对乐高模块关系路径检测,用于检测路径名的正确性及路径层级的正确性:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// 可选开启URL路径验证
[XFURLRoute enableVerifyURLRoute];
// 注册APP的所有URL组件
[BDJAppURLRegister urlRegister];
// 根据URL显示组件
XF_ShowURLComponent2Window_Fast(@"bdj://indexTab")
return YES;
}注意: 例子中的代码来自一个通过乐高框架编写的完整项目:BDJProjectExample