[TOC]
初始化Weex環(huán)境
- WXSDKEngine:SDK開放的絕大多數(shù)接口都在此有聲明。
- WXLog: 控制Log輸出的級(jí)別,包括Verbose、Debug娃惯、Info、Warning肥败、Error趾浅,開發(fā)者可以按需來設(shè)置輸出級(jí)別。
- WXDebugTool: weex提供的對外調(diào)試工具馒稍。
- WXAppConfiguration: 使用weex開發(fā)的業(yè)務(wù)性配置皿哨。
在AppDelegate的didFinishLaunchingWithOptions方法中進(jìn)行初始化設(shè)置
// 業(yè)務(wù)配置,非必需
[WXAppConfiguration setAppGroup:@"itheimaApp"];
[WXAppConfiguration setAppName:@"WeexDemo"];
[WXAppConfiguration setAppVersion:@"3.2.0"];
// 初始化`WeexSDK`環(huán)境
[WXSDKEngine initSDKEnviroment];
// 注冊自定義組件和模型纽谒,非必需 [如果有就注冊如果沒有就不注冊]
[WXSDKEngine registerComponent:@"YourView" withClass:[MyViewComponent class]];
[WXSDKEngine registerModule:@"YourModule" withClass:[YourModule class]];
// 注冊協(xié)議的實(shí)現(xiàn)類证膨,非必需
[WXSDKEngine registerHandler:[WXNavigationDefaultImpl new] withProtocol:@protocol(WXNavigationProtocol)];
//設(shè)置Log輸出等級(jí):調(diào)試環(huán)境默認(rèn)為Debug,正式發(fā)布會(huì)自動(dòng)關(guān)閉鼓黔。
[WXLog setLogLevel:WXLogLevelDebug];
渲染W(wǎng)eex實(shí)例
- 聲明屬性instance
// WXSDKInstance屬性
@property (nonatomic, strong) WXSDKInstance *weexInstance;
// Weex視圖
@property (weak, nonatomic) UIView *weexView;
- 創(chuàng)建WXSDKInstance 對象,并進(jìn)行相關(guān)設(shè)置央勒。
WXSDKInstance酱吝,就是weex渲染的實(shí)例對象喻圃。它提供給開發(fā)者諸多跟頁面渲染相關(guān)的接口,包括renderWithURL娱俺、refreshInstance以及destroyInstance等缎谷,提供了幾個(gè)比較重要的回調(diào)接口井濒,方便開發(fā)者根據(jù)不同的業(yè)務(wù)場景去處理他們的邏輯,如onfailed慎陵,還提供了性能監(jiān)控相關(guān)的接口眼虱。
- (void)renderWeexWithURL:(NSString *)url
{
// 創(chuàng)建WXSDKInstance對象
_weexInstance = [[WXSDKInstance alloc] init];
// 設(shè)置weexInstance所在的控制器
_weexInstance.viewController = self;
//設(shè)置weexInstance的frame
_weexInstance.frame = self.view.frame;
__weak typeof(self) weakSelf = self;
//設(shè)置weexInstance創(chuàng)建完畢回調(diào)
_weexInstance.onCreate = ^(UIView *view) {
weakSelf.weexView = view;
[weakSelf.weexView removeFromSuperview];
[weakSelf.view addSubview:weakSelf.weexView];
};
// 設(shè)置weexInstance出錯(cuò)的回調(diào)
_weexInstance.onFailed = ^(NSError *error) {
//process failure
NSLog(@"處理失敗:%@",error);
};
//設(shè)置渲染完成的回調(diào)
_weexInstance.renderFinish = ^ (UIView *view) {
//process renderFinish
NSLog(@"渲染完成");
};
//設(shè)置weexInstance用于渲染的`js`的URL路徑
[_weexInstance renderWithURL:url options:@{@"bundleUrl":[self.url absoluteString]} data:nil];
}
// 需要在控制器的dealloc方法中銷毀WeexInstance否則會(huì)導(dǎo)致內(nèi)存泄露
- (void)dealloc {
// 銷毀WXSDKInstance實(shí)例
[self.instance destroyInstance];
}
加載Weex的js文件
weex的js文件一般都是從服務(wù)器上加載,如果你不想從服務(wù)器上加載weex的js文件,你可以把這些js文件拷貝到工程目錄中。
- 使用.we文件生成weex的js文件
終端cd
到 .we文件所在的目錄,然后執(zhí)行
weex list.we -o list.js
其中l(wèi)ist.we 是你的頁面對應(yīng)的weex文件. 在開發(fā)中index.we一般指的使用整個(gè)App的入口文件. 我們這里使用list.we 文件,生成一個(gè)list.js文件
- js文件的URL
// 加載本地資源目錄中的js文件
[_instance renderWithURL:[[NSBundle mainBundle] URLForResource:@"list" withExtension:@"js"]];
// 從服務(wù)器加載js文件
[_instance renderWithURL:[NSURL URLWithString:@"http://10.0.100.139:8081/weex.js"]];
Weex開發(fā)的組件骨架和生命周期
<template>
</template>
<style>
</style>
<script>
module.exports = {
data: {},
methods: {},
init: function () {
console.log('在初始化內(nèi)部變量席纽,并且添加了事件功能后被觸發(fā)');
},
created: function () {
console.log('完成數(shù)據(jù)綁定之后,模板編譯之前被觸發(fā)');
},
ready: function () {
console.log('模板已經(jīng)編譯并且生成了 Virtual DOM 之后被觸發(fā)');
},
destroyed: function () {
console.log('在頁面被銷毀時(shí)調(diào)用');
}
}
</script>
- template中主要是組件的引用撞蚕,大體頁面布局润梯。類似于HTML。
- style中主要是組件的CSS樣式引用
- script中主要就是js的調(diào)用甥厦。- data屬于綁定的數(shù)據(jù)纺铭,init、created刀疙、ready是Weex的生命周期方法舶赔。
- methods中存放用戶定義的一些js事件。
- computed中主要是對綁定數(shù)據(jù)data部分進(jìn)行預(yù)處理谦秧。
- init內(nèi)一般用于初始化一些內(nèi)部變量竟纳,綁定一些自定義事件撵溃,這時(shí)還沒有數(shù)據(jù)綁定,沒有創(chuàng)建vdom锥累,所以不能通過this獲取到data和methods缘挑,也不能獲取vdom的節(jié)點(diǎn)
- created 完成了數(shù)據(jù)綁定 ,但還未開始編譯模板桶略,可以通過this獲取data和methods语淘,但不能獲取vdom的節(jié)點(diǎn)
- ready表示渲染完成 ,從子組件往上觸發(fā)
- destroyed 組件銷毀际歼,比如頁面跳轉(zhuǎn)惶翻,從子組件開始往上觸發(fā)
模板(Module)擴(kuò)展
1、自定義Module
- 自定義的module類 必須實(shí)現(xiàn)
WXModuleProtocol
- 必須添加宏
WX_EXPORT_METHO
, 這樣它才可以被weex識(shí)別鹅心,它的參數(shù)是==JavaScript調(diào)用 module指定方法的參數(shù)== - 添加
@synthesized weexInstance
吕粗,每個(gè)moudle對象被綁定到一個(gè)指定的實(shí)例上 - Module 方法會(huì)在UI線程中被調(diào)用,所以不要做太多耗時(shí)的任務(wù)在這里巴帮,如果要在其他線程執(zhí)行整個(gè)module 方法溯泣,需要實(shí)現(xiàn)WXModuleProtocol中- (NSThread *)targetExecuteThread的方法,這樣榕茧,分發(fā)到這個(gè)module的任務(wù)會(huì)在指定的線程中運(yùn)行
- Weex 的參數(shù)可以是 String 或者M(jìn)ap
- Module 支持返回值給 JavaScript中的回調(diào)垃沦,回調(diào)的類型是WXModuleCallback,回調(diào)的參數(shù)可以是String或者M(jìn)ap
@implementation WXEventModule
@synthesize weexInstance;
WX_EXPORT_METHOD(@selector(openTLDURL:callback))
- (void)openTLDURL:(NSString *)url callback:(WXModuleCallback)callback {
NSString *newURL = url;
if ([url hasPrefix:@"http://"]) {
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、注冊這個(gè)Module
通過調(diào)用 WXSDKEngine 中的 registerModule:withClass
方法來注冊自己的module
[WXSDKEngine registerModule:@"tldevent" withClass:[WXEventModule class]];
3用押、使用這個(gè)Module
這里的 require 里面的tldevent 就是在 上一步調(diào)用registerModule: 注冊module 時(shí)候的name
var eventModule = weex.requireModule('tldevent');
eventModule.openTLDURL('url',function(ret) {
nativeLog(ret);
});
組件(Components)擴(kuò)展
雖然 WeexSDK 中有很多的 native 的 Component肢簿,但這有可能并不能滿足需求。如果在之前已經(jīng)寫了一些很酷炫 native 的組件蜻拨,想包裝一下池充,導(dǎo)入到 Weex 中,可以實(shí)現(xiàn)自己的 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>
協(xié)議的實(shí)現(xiàn)(handler)
Weex SDK沒有圖片下載
卧惜,navigation 操作的能力
,需要自己實(shí)現(xiàn)這些 protocol
1夹纫、實(shí)現(xiàn)協(xié)議(以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:@"http://"]) {
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渲染的時(shí)候是按照寬度為750像素標(biāo)準(zhǔn)來渲染的,然后根據(jù)屏幕的實(shí)際寬度來進(jìn)行等比例縮放高度舰讹,所以會(huì)導(dǎo)致Plus系列會(huì)高度變大茅姜、顯示不開,5系列會(huì)高度變小月匣、底部有空白钻洒。我是根據(jù)屏幕實(shí)際寬度和scale來計(jì)算縮放倍數(shù)奋姿,然后設(shè)置實(shí)際的高度的,不知道還有沒有其他好的處理方法航唆。(字體也會(huì)是這種情況胀蛮,在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;