-
Notifications
You must be signed in to change notification settings - Fork 0
使用 JSPatch 开发功能模块
JSPatch 可以用于开发功能模块,把一部分业务完全用 JS 开发,再动态下发给客户端执行,让 APP 同时拥有原生体验和动态特性,并且可以沿用 OC 的思维,使用所有 OC 库以及 JS 工具库进行开发。
使用 JSPatch 开发功能模块有一些新接口建议使用:
##autoConvertOCType()
JSPatch 对 NSDictionary
/ NSArray
/ NSString
/ NSDate
这几个类型从 OC 传递到 JS 时不会自动转为 JS 对应的 Object
/ Array
/ String
/ Date
类型,而是当成一个普通的 OC 对象,于是在 JS 端这些类型就存在两种对象,一种 OC 对象一种 JS 原生对象,详见[这里](https://github.com/bang590/JSPatch/wiki/JSPatch-常见问题#字符串 / 数组 / 字典 操作问题)。
在开发功能模块时这点会造成较大困扰,于是建议在开头执行:
autoConvertOCType(1);
这样所有 NSDictionary
/ NSArray
/ NSString
/ NSDate
返回到 JS 时会自动转为 JS 对应类型,JS 上只有一种类型,同时也不能再调用这些类型的 OC 方法:
//OC
@implementation JPTestObject
+ (NSMutableDictionary *)info {
return @{@"k": @"v"};
}
+ (NSArray *)users {
return @[@"alex", @"bang", @"cat"];
}
@end
autoConvertOCType(1);
var info = JPTestObject.info();
var users = JPTestObject.users();
//info/users 是 js 类型,直接用JS语法操作:
console.log(info['k']);
console.log(users[0]);
//调用它们的 OC 方法是不允许的:
info.objectForKey('k'); //crash
users.objectAtIndex(1); //crash
//若临时必须调用这些对象的 OC 方法,可以先关闭再开启自动转换:
autoConvertOCType(0);
var ocInfo = JPTestObject.info();
console.log(ocInfo.objectForKey('k')) //OK
autoConvertOCType(1);
##defineJSClass()
开发功能时会创建很多类,有些是需要继承自 OC 类的,例如 VC 层需要继承 UIView 和 UIViewController,有些是不需要继承 OC 类的,例如 M 层用于数据操作的类。在 JS 创建这些类实际上不需要跟 OC 发生关系,建议使用 defineJSClass()
定义这些类,性能上会有很大提升。
示例:
defineJSClass('JPBaseDataSource', {
init: function() {
this.baseData = [1,2,3];
}
});
var _dataSourceShareInstance;
defineJSClass('JPDataSource : JPBaseDataSource', {
init: function(){
this.super().init();
this.data = this.baseData.concat([4,5,6]);
return this;
},
readDataAtIndex: function(i) {
return this.data[i]
},
}, {
shareInstance: function(){
if (!_dataSourceShareInstance) {
_dataSourceShareInstance = JPDataSource.alloc().init();
}
return _dataSourceShareInstance;
},
})
var dataSource = JPDataSource.shareInstance();
dataSource.readDataAtIndex(1)
可以看到 defineJSClass()
的使用方式跟 defineClass()
几乎一样,方法定义 / 对象生成 / 实例方法和类方法定义 / 继承的写法 / super的写法 都是一样的,只有两点不同:
- 用 this 关键字代替 self
- property 不用 getter/setter,直接存取。
##include() / resourcePath()
可以用 include()
接口引入其他 js 文件,路径为执行的主程序所在目录的相对路径,例如:
- js
- main.js
- JPDataSource.js
- controllers
- JPViewController.js
- views
- JPView.js
- img
- demo.png
以 main.js
为主程序 (传入 [JPEngine evaluateScriptWithPath:@""]
执行),main.js
所在目录就是根目录,include 时填相对这个目录的路径:
//main.js
include('JPDataSource.js');
include('controllers/JPViewController.js');
//JPViewController.js
include('views/JPView.js');
此外可以通过 resourcePath()
获取资源文件的实际路径,路径规则与 include()
一样:
//JPView.js
var path = resourcePath('img/demo.png');
var image = require('UIImage').imageWithContentsOfFile(path);
##其他
defineClass()
创建的方法如果确定不会在 OC 调用到 (不是 protocol / target action 方法),也不会被使用者调用,完全是私有方法,建议以下划线 _
开头命名,这样可以减少不必要的 OC 方法注册。
##Demo
其他写法可以参考 Dribbble Demo。