本文作者:imweb helondeng 原文出处:imweb社区 未经同意,禁止转载
随着React-Native的火爆,以及Native和Web开发本身的一些痛点,近期团队考虑将iOS App中部分界面迁移到React-Native上,本文主要谈谈开发过程中遇到的一些问题及解决方案。
图片来源有2种:local 和 remote。
remote图片是通过http请求来处理的。
<Image source={{url:'http://10.url.cn/xx.jpg'}}
这种方式的优势:
缺点很明显:
local图片的引入方式有好几种:
绝对路径,将图片放在App某个目录下,在项目中引用。
// iOS App资源方式
<Image source={ require(image!icon1) } />
// base64
<Image source={{ isStatic: true, url: 'data:image/jpeg;base64,'+ base64 }} />
// absolute path
<Image source={{ isStatic: true, url: '/Users/xxx/xxx.jpg' }} />
最终采用了绝对路径的方式,基于以下几点:
同时,带来了另一个问题:JS中引用图片时,实际只知道图片相对于JS的路径,最终应用安装到哪个路径下是不知道的。解决方式是,通过Native接口,将路径前缀通知到Web,然后由Web将相对路径图片拼接成绝对路径,同时,将这个路径前缀缓存,避免重复调用。
facebook提供2种方式集成react-native代码:online 和 offline。对应的OC引入JS的方式:
// online
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"];
// offline
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
online方式走http请求,响应延时大,但更新方便;offline走本地资源方式,将相关资源打入安装包,请求响应快,更新依赖客户端。
最终采用了offline + 离线包方案,将资源打成离线包,放入安装包中。后续有更新时,将离线包上传到离线包管理平台,每次打开React-Native相关界面时,native会发起CGI请求,检查现网是否有最新版本的离线包,如果有,CGI会返回最新的离线包地址,Native下载最新的离线包,解压到本地,下次访问时,即可访问最新的代码。
这里提到的通讯,更多是数据层面的通讯。在实现课程列表页时,点击上面的菜单,下面的课程列表数据要变化。
这是在实现上,是3个组件:页面本身Page,菜单list,课程list。菜单list和课程list被Page引用,两者之间的数据通讯,需要通过Page来传递。
render: function() {
return (
this.state.mt}
st={this.state.st}
tt={this.state.tt} />
this._setCatsId} />
)
},
_setCatsId: function(name, val) {
// 修改 Page 的state
}
主要通讯逻辑:
JS-OC之间的通讯机制,这里已经写的很清楚了,主要是双方保存了同样一份模块注册表。
在图片加载那里,Native提供了一个获取地址前缀的接口,主要代码片段:
@implementation EduProvidePathToJS
// 注册模块
RCT_EXPORT_MODULE();
// 注册方法,会将方法和模块写入到注册表中。
RCT_EXPORT_METHOD(getPath:(RCTResponseSenderBlock)callback) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pathToWebappCacheInDocuments = [documentPath stringByAppendingPathComponent:@"webappCache2"];
callback(@[pathToWebappCacheInDocuments]);
}
@end
JS调用逻辑
// 引入模块
var ProvidePathToJS = require('NativeModules').EduProvidePathToJS;
// 调用方法
ProvidePathToJS.getPath(function(path) {
});
React-Native使用了flexbox布局,在居中和等分上有一定的优势。其中,没有“层”的概念,也就是说z-index这货是无效的,默认都在同一层,后面的会覆盖前面的,用这种方式模拟“层”。 另外一些坑:
从目前的Css代码迁移到React-Native,感觉有很多适配工作。
9月会跟着iOS的版本,带一部分React-Native的代码到外网,搜集到数据后,后面会在iOS慢慢铺开使用。