iCoder

Weex开发 [iOS]

2017-03-03  本文已影响655人  大斌小姜

[TOC]

初始化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实例

  1. 声明属性instance
// WXSDKInstance属性
@property (nonatomic, strong) WXSDKInstance *weexInstance;
// Weex视图
@property (weak, nonatomic) UIView *weexView;
  1. 创建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文件拷贝到工程目录中。

  1. 使用.we文件生成weex的js文件
    终端cd 到 .we文件所在的目录,然后执行
weex  list.we -o list.js

其中list.we 是你的页面对应的weex文件. 在开发中index.we一般指的使用整个App的入口文件. 我们这里使用list.we 文件,生成一个list.js文件

  1. 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>

模板(Module)扩展

1、自定义Module

  1. 自定义的module类 必须实现 WXModuleProtocol
  2. 必须添加宏WX_EXPORT_METHO, 这样它才可以被weex识别,它的参数是==JavaScript调用 module指定方法的参数==
  3. 添加@synthesized weexInstance,每个moudle对象被绑定到一个指定的实例上
  4. Module 方法会在UI线程中被调用,所以不要做太多耗时的任务在这里,如果要在其他线程执行整个module 方法,需要实现WXModuleProtocol中- (NSThread *)targetExecuteThread的方法,这样,分发到这个module的任务会在指定的线程中运行
  5. Weex 的参数可以是 String 或者Map
  6. 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

  1. 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;
上一篇下一篇

猜你喜欢

热点阅读