美文网首页iCoder
Weex开发 [iOS]

Weex开发 [iOS]

作者: 大斌小姜 | 来源:发表于2017-03-03 16:55 被阅读655次

    [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实例

    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>
    
    • 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

    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;
    

    相关文章

      网友评论

      • 今天明天087:你好有dome可以看看吗
      • b4547c0e3062:你好,我在扩展moudle的时候添加@synthesized weexInstance时报错,Property implementation must have its declaration in interface 'myMoudle',这个怎么解

      本文标题:Weex开发 [iOS]

      本文链接:https://www.haomeiwen.com/subject/ubdrgttx.html