干货:Weex入门与进阶指南
弁言
比拟力于React Native的“Learn once, write anywhere”,Weex的标语是“Write once, run everywhere”。思索到React Native比力任性的向下兼容性,我们也引入了Weex做一番了解。
本文主要分为以下几个局部:
-
构建Hello World步骤;
-
集成到现有的iOS工程中;
-
使用Weex的高等特性;
-
怎样以Weex做奉献;
1Weex入门
1.1 Hello Weex
参考官方教程,我们必要先安装Node。在Mac上也可以经过Homebrew直接举行安装:brew install node。
接着我们必要安装Weex CLI:npm install -g weex-toolkit,并确保版本号大于0.1.0:
$ weex –version
info 0.3.4
至此,准备事情以前到位,我们可以开头编写Weex步骤了。
创建一个名为helloweex.we的文件,并编写以下代码:
<template>
<div>
<text>Hello Weex</text>
</div></template>
经过下令行在helloweex.we文件地点的目次下实行如下下令:
$ weex helloweex.we
info Fri Jul 08 2016 14:30:31 GMT+0800 (CST)WebSocket is listening on port 8082 info Fri Jul 08 2016 14:30:31 GMT+0800 (CST)http is listening on port 8081
此时,欣赏器会掀开一个新的标签页展现helloweex.we的实行后果:
注意到此时地点栏的内容包含着
http://127.0.0.1:8081/weex_tmp/h5_render/?hot-reload_controller&page=helloweex.js&loader=xhrhot reload字样,以是可以天然遐想到当我们在源文件做修正并保存后,该页面会主动改造展现后果。
1.2 基本布局
外表的示例只是一个十分简便的雏形,而一个比力完备的Weex步骤包含三个局部:模板(Template)、样式(Style)和脚本(Script)。
好比我们可以使用上文提到的hot reload,修要文本的颜色并及时查察后果:
<template>
<div>
<text class=”title”>Hello Weex</text>
</div></template><style>
.title { color: red; }</style>
接着我们添加上第三构成局部:脚本(Script):
<template>
<div>
<text class=”title” onclick=”onClickTitle”>Hello Weex</text>
</div></template><style>
.title { color: red; }</style><script>
module.exports = {
methods: {
onClickTitle: function (e) { console.log(e);
alert(‘title clicked.’);
}
}
}</script>
如此一来,当我们点击文本的时分会显现如下后果:
更多语法干系内容可以参考官方文档。
2集成到iOS工程
2.1 概述
外表是从前端的角度来开头看Weex的基本后果,关于客户端来讲,这类框架的一个上风就是可以团结Native代码发扬作用。好比在人手告急的情况下可以一次开发,然后使用在不同平台终端上。
以是,这里讨论下怎样将其集成到现有的iOS工程项目中间。
-
参考官方文档,我们先从GitHub下载Weex源码。
-
解压后将目次下的
ios/sdk复制到现有的iOS工程目次下,并依据相对途径更新既有工程的podfile,然后实行pod update将Weex iOS SDK集成进既有的iOS项目中; -
在iOS Native代码中初始化Weex SDK,然后创建出要展现Weex步骤的ViewController,具体见如下形貌;
2.2 在iOS使用上运转Weex步骤
在怎样集成的文档中,前方说的比力清晰,但是在初始化Weex情况和渲染Weex实例这两个末节中,约莫是由于代码是从比力大的项目源码中摘录出来的,以是存在一些不必要或没有上下文的代码。
这里形貌下在开发调试阶段运转Weex步骤。
2.2.1 确定要运转的Weex步骤
创建一个WeexDebugViewController,举行如下布局:
经过填入IP和文件名来定位我们要运转的Weex步骤。别的,还可以团结weex helloweex.we --qr -h {ip or hostname}下令来天生二维码,举行扫描演示,不外剖析二维码照旧为了获取到Weex步骤地点地点。
2.2.2 初始化Weex SDK
开发调试阶段我们可以先将Weex SDK的初始化放在这个WeexDebugViewController中:
– (void)initWeex { static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[WXAppConfiguration setAppGroup:@”AliApp”];
[WXAppConfiguration setAppName:@”WeexDemo”];
[WXAppConfiguration setAppVersion:@”1.0.0″];
[WXSDKEngine initSDKEnviroment];
[WXLog setLogLevel:WXLogLevelVerbose];
});
}
2.2.3 运转Weex步骤的ViewController
点击ShowWeex按钮时,我们可以依据两个输入框的内容拼接出要运转的Weex步骤的地点,然后将其赋值给用来渲染Weex实例的:
WeexShowcaseViewController
– (void)showWeex { NSString *str = [NSString stringWithFormat:@”http://%@:8081/%@”, self.ipField.text, self.filenameField.text];
WeexShowcaseViewController *vc = [WeexShowcaseViewController new];
vc.weexUri = [NSURL URLWithString:str];
[self.navigationController pushViewController:vc animated:YES];
}
接着我们来看看的源码:
WeexShowcaseViewController
#import <WeexSDK/WeexSDK.h>@interface WeexShowcaseViewController ()@property (nonatomic, strong) WXSDKInstance *weexSDK;@end@implementation WeexShowcaseViewController- (void)dealloc {
[_weexSDK destroyInstance];
}
– (void)viewDidLoad {
[super viewDidLoad]; // Do any additional setup after loading the view.
self.weexSDK.viewController = self; self.weexSDK.frame = self.view.frame;
[self.weexSDK renderWithURL:self.weexUri];
__weak typeof(self) weakSelf = self; self.weexSDK.onCreate = ^(UIView *view) {
[weakSelf.view addSubview:view];
}; self.weexSDK.renderFinish = ^(UIView *view) {
;
}; self.weexSDK.onFailed = ^(NSError *error) { NSLog(@”weexSDK onFailed : %@\n”, error);
};
}
– (WXSDKInstance *)weexSDK { if (!_weexSDK) {
_weexSDK = [WXSDKInstance new];
} return _weexSDK;
}
2.2.4 运转起来
回到终端上,切换到helloweex.we文件地点的目次,将Weex的dev server跑起来:
$ weex -s .
info Fri Jul 08 2016 15:38:59 GMT+0800 (CST)http is listening on port 8081 info we file in local path . will be transformer to JS bundle
please access http://30.9.112.173:8081/
然后在Native上填入对应的IP和步骤文件名:
到此,将Weex集成到现有iOS工程中算开头告一段落。
3Weex进阶
当集成事情完成后,会察觉现有功效不敷以满意业务需求,以是Weex支持开发者做一些扩展。
3.1 完成Weex接口协议
之前的helloweex.we示例中仅有一个文本元素,如今再添加一个图片元素:
<template>
<div>
<image class=”thumbnail” src=”http://image.coolapk.com/apk_logo/2015/0817/257251_1439790718_385.png”></image>
<text class=”title” onclick=”onClickTitle”>Hello Weex</text>
</div></template><style>
.title { color: red; }
.thumbnail { width: 100; height: 100; }</style><script>
module.exports = {
methods: {
onClickTitle: function (e) { console.log(e);
alert(‘title clicked.’);
}
}
}</script>
然后再实行:$ weex helloweex.we来运转查察后果:
可以在欣赏器里看到这次多了一张图片。但是假如是运转在Native端,图片则得不到展现:
这是由于Weex SDK没有提供图片下载才能,必要我们来完成。
3.2 完成图片下载协议WXImgLoaderProtocol
这个基本可以参考官方文档来完成。
3.2.1 界说图片下载Handler
#import <WeexSDK/WeexSDK.h>@interface WeexImageDownloader : NSObject <WXImgLoaderProtocol>@end
3.2.2 完成协议接口
这个类必需依照WXImgLoaderProtocol协议,并完成该协议界说的接口:
#import “WeexImageDownloader.h”#import <SDWebImage/SDWebImageManager.h>@implementation WeexImageDownloader- (id<WXImageOperationProtocol>)downloadImageWithURL:(NSString *)url
imageFrame:(CGRect)imageFrame
userInfo:(NSDictionary *)options
completed:(void(^)(UIImage *image, NSError *error, BOOL finished))completedBlock { 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);
}
}];
}@end
3.2.3 注册Handler
[WXSDKEngine registerHandler:[WeexImageDownloader new] withProtocol:@protocol(WXImgLoaderProtocol)];
如此一来,再次运转步骤就可以看到图片了:
如此计划的利益主要是思索了不同App依托的网络库大概图片下载缓存库不同,制止Weex强依托于一些第三方库,依照依托笼统而不是具体的准则。
BTW,我一局部以为Weex缩写成WX,WeexImageLoaderProtocol缩写成WXImgLoaderProtocol,不是很顺眼。
3.2 自界说UI组件
假如Weex的内置标签不敷以满意要求时,我们可以自界说Native组件,然后暴露给.we文件使用。
好比我们可以界说一个WeexButton,承继自WXComponent,然后将其注册进Weex SDK:
[WXSDKEngine registerComponent:@”weex-button” withClass:[WeexButton class]];
如此一来,我们就可以在.we文件中使用这个标签了:
<weex-button class=”button” title=”hello”></weex-button>
标签中的属性我们可以在初始化函数中取得:
– (instancetype)initWithRef:(NSString *)ref
type:(NSString*)type
styles:(nullable NSDictionary *)styles
attributes:(nullable NSDictionary *)attributes
events:(nullable NSArray *)events
weexInstance:(WXSDKInstance *)weexInstance {
self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]; if (self) {
_title = [WXConvert NSString:attributes[@”title”]];
} return self;
}
经过这些属性,我们可以在组件生命周期中修正组件的样式,好比设置按钮的title:
– (void)viewDidLoad {
[super viewDidLoad]; self.innerButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; self.innerButton.frame = self.view.bounds;
[self.view addSubview:self.innerButton];
[self.innerButton setTitle:self.title forState:UIControlStateNormal];
[self.innerButton addTarget:self action:@selector(onButtonClick:) forControlEvents:UIControlEventTouchUpInside];
}
3.3 自界说模块
除了UI组件之外,有些时分我们渴望JS层面可以调用Native的一些功效,好比经过JS代码让Native掀开一个特定的ViewController。这时分,我们可以自界说一个模块向JS层面暴露API:
@synthesizeweexInstance;WX_EXPORT_METHOD(@selector(call:withParam:callback:))-(void)call:(NSString *)api withParam:(NSDictionary *)param callback:(WXModuleCallback)callback {
注意点如下:
-
必要依照
WXModuleProtocol协议; -
必要构成(
synthesize)weexInstance属性; -
使用
WX_EXPORT_METHOD来暴露API; -
使用
WXModuleCallback举行回调;
完成以上编码后,向Weex SDK注册:[WXSDKEngine registerModule:,就可以在.we文件中使用了:
<script>
module.exports = {
methods: {
onClickTitle: function (e) { var mymodule = require(‘@weex-module/mymodule’);
mymodule.call(‘api’, {}, function(ret) {
});
}
}
}</script>
4为Weex做奉献
由于Weex刚开源不久,假如开发者发觉一些成绩大概必要改良的场合,可以直接在GitHub上举行fork,修正完后提交Pull Request。
更多深度武艺内容,请眷注云栖社区微信群众号:yunqiinsight。

















