[TOC]
初始化Weex环境
- WXSDKEngine:SDK开放的绝大多数接口都在此有声明。
- WXLog: 控制Log输出的级别,包括Verbose、Debug、Info、Warning、Error,开发者可以按需来设置输出级别。
- WXDebugTool: weex提供的对外调试工具。
- WXAppConfiguration: 使用weex开发的业务性配置。
在AppDelegate的didFinishLaunchingWithOptions方法中进行初始化设置
// 业务配置,非必需
[WXAppConfiguration setAppGroup:@"itheimaApp"];
[WXAppConfiguration setAppName:@"WeexDemo"];
[WXAppConfiguration setAppVersion:@"3.2.0"];
// 初始化`WeexSDK`环境
[WXSDKEngine initSDKEnviroment];
// 注册自定义组件和模型,非必需 [如果有就注册如果没有就不注册]
[WXSDKEngine registerComponent:@"YourView" withClass:[MyViewComponent class]];
[WXSDKEngine registerModule:@"YourModule" withClass:[YourModule class]];
// 注册协议的实现类,非必需
[WXSDKEngine registerHandler:[WXNavigationDefaultImpl new] withProtocol:@protocol(WXNavigationProtocol)];
//设置Log输出等级:调试环境默认为Debug,正式发布会自动关闭。
[WXLog setLogLevel:WXLogLevelDebug];
渲染Weex实例
- 声明属性instance
// WXSDKInstance属性
@property (nonatomic, strong) WXSDKInstance *weexInstance;
// Weex视图
@property (weak, nonatomic) UIView *weexView;
- 创建WXSDKInstance 对象,并进行相关设置。
WXSDKInstance,就是weex渲染的实例对象。它提供给开发者诸多跟页面渲染相关的接口,包括renderWithURL、refreshInstance以及destroyInstance等,提供了几个比较重要的回调接口,方便开发者根据不同的业务场景去处理他们的逻辑,如onfailed,还提供了性能监控相关的接口。
- (void)renderWeexWithURL:(NSString *)url
{
// 创建WXSDKInstance对象
_weexInstance = [[WXSDKInstance alloc] init];
// 设置weexInstance所在的控制器
_weexInstance.viewController = self;
//设置weexInstance的frame
_weexInstance.frame = self.view.frame;
__weak typeof(self) weakSelf = self;
//设置weexInstance创建完毕回调
_weexInstance.onCreate = ^(UIView *view) {
weakSelf.weexView = view;
[weakSelf.weexView removeFromSuperview];
[weakSelf.view addSubview:weakSelf.weexView];
};
// 设置weexInstance出错的回调
_weexInstance.onFailed = ^(NSError *error) {
//process failure
NSLog(@"处理失败:%@",error);
};
//设置渲染完成的回调
_weexInstance.renderFinish = ^ (UIView *view) {
//process renderFinish
NSLog(@"渲染完成");
};
//设置weexInstance用于渲染的`js`的URL路径
[_weexInstance renderWithURL:url options:@{@"bundleUrl":[self.url absoluteString]} data:nil];
}
// 需要在控制器的dealloc方法中销毁WeexInstance否则会导致内存泄露
- (void)dealloc {
// 销毁WXSDKInstance实例
[self.instance destroyInstance];
}
加载Weex的js文件
weex的js文件一般都是从服务器上加载,如果你不想从服务器上加载weex的js文件,你可以把这些js文件拷贝到工程目录中。
- 使用.we文件生成weex的js文件
终端cd
到 .we文件所在的目录,然后执行
weex list.we -o list.js
其中list.we 是你的页面对应的weex文件. 在开发中index.we一般指的使用整个App的入口文件. 我们这里使用list.we 文件,生成一个list.js文件
- js文件的URL
// 加载本地资源目录中的js文件
[_instance renderWithURL:[[NSBundle mainBundle] URLForResource:@"list" withExtension:@"js"]];
// 从服务器加载js文件
[_instance renderWithURL:[NSURL URLWithString:@"http://10.0.100.139:8081/weex.js"]];
Weex开发的组件骨架和生命周期
<template>
</template>
<style>
</style>
<script>
module.exports = {
data: {},
methods: {},
init: function () {
console.log('在初始化内部变量,并且添加了事件功能后被触发');
},
created: function () {
console.log('完成数据绑定之后,模板编译之前被触发');
},
ready: function () {
console.log('模板已经编译并且生成了 Virtual DOM 之后被触发');
},
destroyed: function () {
console.log('在页面被销毁时调用');
}
}
</script>
- template中主要是组件的引用,大体页面布局。类似于HTML。
- style中主要是组件的CSS样式引用
- script中主要就是js的调用。- data属于绑定的数据,init、created、ready是Weex的生命周期方法。
- methods中存放用户定义的一些js事件。
- computed中主要是对绑定数据data部分进行预处理。
- init内一般用于初始化一些内部变量,绑定一些自定义事件,这时还没有数据绑定,没有创建vdom,所以不能通过this获取到data和methods,也不能获取vdom的节点
- created 完成了数据绑定 ,但还未开始编译模板,可以通过this获取data和methods,但不能获取vdom的节点
- ready表示渲染完成 ,从子组件往上触发
- destroyed 组件销毁,比如页面跳转,从子组件开始往上触发
模板(Module)扩展
1、自定义Module
- 自定义的module类 必须实现
WXModuleProtocol
- 必须添加宏
WX_EXPORT_METHO
, 这样它才可以被weex识别,它的参数是==JavaScript调用 module指定方法的参数== - 添加
@synthesized weexInstance
,每个moudle对象被绑定到一个指定的实例上 - Module 方法会在UI线程中被调用,所以不要做太多耗时的任务在这里,如果要在其他线程执行整个module 方法,需要实现WXModuleProtocol中- (NSThread *)targetExecuteThread的方法,这样,分发到这个module的任务会在指定的线程中运行
- Weex 的参数可以是 String 或者Map
- Module 支持返回值给 JavaScript中的回调,回调的类型是WXModuleCallback,回调的参数可以是String或者Map
@implementation WXEventModule
@synthesize weexInstance;
WX_EXPORT_METHOD(@selector(openTLDURL:callback))
- (void)openTLDURL:(NSString *)url callback:(WXModuleCallback)callback {
NSString *newURL = url;
if ([url hasPrefix:@"//"]) {
newURL = [NSString stringWithFormat:@"http:%@", url];
} else if (![url hasPrefix:@"http"]) {
newURL = [NSURL URLWithString:url relativeToURL:weexInstance.scriptURL].absoluteString;
}
UIViewController *controller = [[WXDemoViewController alloc] init];
((WXDemoViewController *)controller).url = [NSURL URLWithString:newURL];
[[weexInstance.viewController navigationController] pushViewController:controller animated:YES];
callback(@{@"result":@"success"});
}
@end
2、注册这个Module
通过调用 WXSDKEngine 中的 registerModule:withClass
方法来注册自己的module
[WXSDKEngine registerModule:@"tldevent" withClass:[WXEventModule class]];
3、使用这个Module
这里的 require 里面的tldevent 就是在 上一步调用registerModule: 注册module 时候的name
var eventModule = weex.requireModule('tldevent');
eventModule.openTLDURL('url',function(ret) {
nativeLog(ret);
});
组件(Components)扩展
虽然 WeexSDK 中有很多的 native 的 Component,但这有可能并不能满足需求。如果在之前已经写了一些很酷炫 native 的组件,想包装一下,导入到 Weex 中,可以实现自己的 native Component。(参考官方源码中的WeexPlayGround中的WXSelectComponent)
1、自定义组件
@implementation WXMyComponent
WX_EXPORT_METHOD(@selector(tldfocus)) // 暴露该方法给js
- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance
{
if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {
// handle your attributes
// handle your styles
}
return self;
}
- (void)tldfocus
{
NSLog(@"you got it");
}
@end
2、注册组件
[WXSDKEngine registerComponent:@"mycomponent" withClass:[WXMyComponent class]]
3、组件的使用
<template>
<mycomponent id='mycomponent'></mycomponent>
</template>
<script>
module.exports = {
created:function() {
this.$el('mycomponent').tldfocus();
}
}
</script>
协议的实现(handler)
Weex SDK没有图片下载
,navigation 操作的能力
,需要自己实现这些 protocol
1、实现协议(以WXImgLoaderProtocol为例)
#pragma mark - WXImgLoaderProtocol
- (id<WXImageOperationProtocol>)downloadImageWithURL:(NSString *)url imageFrame:(CGRect)imageFrame userInfo:(NSDictionary *)userInfo completed:(void(^)(UIImage *image, NSError *error, BOOL finished))completedBlock
{
if ([url hasPrefix:@"//"]) {
url = [@"http:" stringByAppendingString:url];
}
return (id<WXImageOperationProtocol>)[[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:url] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, finished);
}
}];
}
2、handler注册
[WXSDKEngine registerHandler:[WXImgLoaderDefaultImpl new] withProtocol:@protocol(WXImgLoaderProtocol)]
Tips
- Weex渲染的时候是按照宽度为750像素标准来渲染的,然后根据屏幕的实际宽度来进行等比例缩放高度,所以会导致Plus系列会高度变大、显示不开,5系列会高度变小、底部有空白。我是根据屏幕实际宽度和scale来计算缩放倍数,然后设置实际的高度的,不知道还有没有其他好的处理方法。(字体也会是这种情况,在5系列上偏小,在Plus系列上偏大)
var config = this.$getConfig();
var env = config.env;
var scale = env.scale;
this.realScale = 750/2*scale/env.deviceWidth
this.rowHeight = this.rowHeight * this.realScale;