深入折腾 Weex,知乎日报客户端开发

简介: 深入折腾了一下 Weex,做了一个知乎日报的客户端,同时实现了一种目前 Weex 尚未提供的 Native 页面切换思路。
深入折腾了一下 Weex,做了一个知乎日报的客户端,同时实现了一种目前 Weex 尚未提供的 Native 页面切换思路。

最后效果如下:



这个 demo 主要实践 4 件事情:

1. 模块注册
2. 组件注册
2. Native 方法调用
4. Native 页面切换 & 参数传递

整个 app 只有两个页面,都是纯 Weex 编写的,对于第一个页面非常的简单,布局类似于 iOS 的 TableView
<template>
  <scroller>
    <container repeat="{{list}}" news_id="{{news_id}}" onclick="onclick">
      <container class="cell">
        <image class="thumb" src="{{src}}"></image>
        <text class="title">{{title}}</text>
      </container>
      <text class="separator"></text>
    </container>
  </scroller>
</template>

然后我们使用 this.$sendHttp 发起 http 请求,这里知道,Weex 仅仅是一个渲染引擎,对于 http 请求,mtop 请求,甚至图片加载等功能,是需要业务注入实现类的。比如 WeexDemo 里面的 sendHttp 就是注入了 WXStreamModule 模块,然后在实现里面使用了 NSURLConnection,这个设计非常不错,在具体的业务当中,你可以把实现代码替换成任何你想要的 HTTP 库。

[WXSDKEngine registerModule:@"image" withClass:[WXImageModule class]];
[WXSDKEngine registerModule:@"stream" withClass:[WXStreamModule class]];
[WXSDKEngine registerModule:@"event" withClass:[WXEventModule class]];

这就是 Weex 注册模块的原理,其中图片模块是用 SDWebImage 实现的。我们同样也可以将其他的 Native 方法注册到模块里面,例如:

WX_EXPORT_METHOD(@selector(log:));

- (void)log:(NSString *)text {
    NSLog(@"LOG: %@", text);
}

然后在 JavaScript 代码里面只需要用 this.$call("event", "log", "Hello, World!"); 就能在 Native 里面输出 Hello World! 这提供了强大的扩展能力。

首页的展示是较为简单的,用的是 Weex 自带的 ImageText,但是详情页是一个 Web 页面,貌似我还没找到 Weex 提供的 WebView 渲染组件。(但是奇怪的是,我自建 WXWebViewComponent 的时候提示 Duplicated Symbol,难道是还未实现么),所以我们需要自建一个 WXComponent,用于 WebView 渲染。

当然我们也可以使用 Native 代码打开一个 WebView,不过这样显然不如纯 Weex 实现有趣。

#import "WXHtmlNodeComponent.h"
#import <WebKit/WebKit.h>

@interface WXHtmlNodeComponent()

@property (nonatomic, strong) NSString *URL;
@property (nonatomic, strong) NSString *html;
@property (nonatomic, strong) WKWebView *webView;

@end

@implementation WXHtmlNodeComponent

WX_CUSTOM_ATTRIBUTE(url, URL, NSString)
WX_CUSTOM_ATTRIBUTE(html, html, NSString)

+ (Class)viewClass {
    return [WKWebView class];
}

- (void)applyPropertiesToView:(UIView *)view {
    [super applyPropertiesToView:view];
    WKWebView *webView = (WKWebView *)view;
    if (self.html.length > 0) {
        [webView loadHTMLString:self.html baseURL:nil];
    } else if (self.URL.length > 0) {
        [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.URL]]];
    }
}

这个 Component 支持 urlhtml 两种 attribute,意味着可以从 url 或者 html 代码渲染他。我们把它注册到 webnode 这个名字上面,就能在详情页使用它了:

<template>
  <container>
    <WebNode url="{{context.url}}" class="webnode"></WebNode>
  </container>
</template>

<script>
  module.exports = {
    data: {
      context: "{{context}}"
    }
  }
</script>

<style>
  .webnode {
    height: 1222;
    flex: 1;
  }
</style>

然后最最关键的事情来了,当用户点击一行的时候,我们要从首页跳到详情页,而这两个页面都是 Weex 的(目前貌似 Weex 没有提供这样的能力)。

但是没有关系,我们有 Module,这里我实现了一套逻辑,包括了本地页面 Push 和 Weex 页面上下文传递逻辑。
- (void)push:(NSDictionary *)params {
    ViewController *controller = [[ViewController alloc] init];
    controller.URL = [NSURL URLWithString:params[@"url"]];
    controller.context = params[@"context"];
    UINavigationController *navigator = [(AppDelegate *)[[UIApplication sharedApplication] delegate] navigator];
    [navigator pushViewController:controller animated:YES];
}

然后在首页 onclick 的时候,只要把 context 带到 Module 里面的 push 方法,往下透传过下一个 Weex 页面,就能完成下个页面的初始化。

onclick: function(e) {
  var news_id = e.target.attr["news_id"];
  var context = this;
  var api = this.api(news_id);
  this.get(api, function(json) {
    var params = {
      url: "next weex url",
      context: {
        url: json.share_url,
        title: json.title
      }
    };
    context.$call("event", "push", params);
  });
}

具体来说,这里面使用了一个数据绑定上面的技巧,我把 weex 页面上的 data 字段放置了一个 "{{context}}"

<script>
  module.exports = {
    data: {
      context: "{{context}}"
    }
  }
</script>

这是一个占位符,会在 Native Code 里面被 Push 传进来的 context 替换(这是一个 NSDictionary),处理的过程只是做一次字符串替换

#import "WXHelper.h"
#import "JSONHelper.h"

@implementation WXHelper

+ (NSString *)scriptWithURL:(NSURL *)URL context:(NSDictionary *)context {
    
    NSString *script = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:nil];
    
    if (context == nil || ![context isKindOfClass:[NSDictionary class]]) {
        return script;
    }
    
    return [script stringByReplacingOccurrencesOfString:@"\"{{context}}\""
                                             withString:JSONStringWithObject(context) ?: @""];
}

@end

然后我们的上下文就会被绑定到下一个 weex 页面,其实根据这个思路,我们可以做更多的 Weex 和本地的交互,甚至把它做成 Framework 方便使用。

整个流程如下:

首页 weex 渲染 --> onclick --> module 传递上下文到下一个 weex --> weex 自定义组件 WebView 渲染

以上就是整个 demo 的完整思路。

最后

Weex 的模块注册、组件注册非常的有用,给业务扩展自己的能力,自定义自己的功能提供了强大的基础。
当然也希望 Weex 可以在 Native 交互方面提供更多有用的方法。

目录
相关文章
|
5月前
|
人工智能 安全 搜索推荐
钉钉发布全球首个工作智能操作系统Agent OS,专为AI打造
AI钉钉1.1版本名为“木兰”,距离钉钉发布AI钉钉1.0版本“蕨”不到四个月。“蕨象征着破土,木兰是破土后的初生。”钉钉创始人、CEO陈航(花名:无招)说,“未来,钉钉上所有AI Agent都基于Agent OS搭建和运行,让AI直连物理世界。”
393 1
|
安全 关系型数据库 文件存储
Websoft9 服务器面板中 Odoo 安装与群晖 NAS 的对比
传统部署Odoo面临基础设施搭建、镜像供应链、复杂配置及运维监控四大难题,而群晖NAS方案存在Docker依赖、插件更新滞后和配置自由度低的局限。Websoft9提供开箱即用的解决方案:无需预装Docker,三键式安装支持全版本Odoo;具备企业级扩展功能如负载均衡与集群部署;兼容混合云架构,支持公有云、私有云及边缘设备管理;同时确保合规性,自动扫描漏洞并生成修复报告,大幅提升部署效率与系统安全性。
|
机器学习/深度学习 测试技术 计算机视觉
RT-DETR改进策略【Conv和Transformer】| ICCV-2023 iRMB 倒置残差移动块 轻量化的注意力模块
RT-DETR改进策略【Conv和Transformer】| ICCV-2023 iRMB 倒置残差移动块 轻量化的注意力模块
409 14
RT-DETR改进策略【Conv和Transformer】| ICCV-2023 iRMB 倒置残差移动块 轻量化的注意力模块
List并发线程安全问题
【10月更文挑战第21天】`List` 并发线程安全问题是多线程编程中一个非常重要的问题,需要我们认真对待和处理。只有通过不断地学习和实践,我们才能更好地掌握多线程编程的技巧和方法,提高程序的性能和稳定性。
809 59
|
数据采集 设计模式 自然语言处理
设计模式最佳套路2 —— 愉快地使用管道模式
管道模式(Pipeline Pattern) 是责任链模式(Chain of Responsibility Pattern)的常用变体之一。在管道模式中,管道扮演着流水线的角色,将数据传递到一个加工处理序列中,数据在每个步骤中被加工处理后,传递到下一个步骤进行加工处理,直到全部步骤处理完毕。 PS:纯的责任链模式在链上只会有一个处理器用于处理数据,而管道模式上多个处理器都会处理数据。
13543 0
设计模式最佳套路2 —— 愉快地使用管道模式
|
机器学习/深度学习 PyTorch API
优化注意力层提升 Transformer 模型效率:通过改进注意力机制降低机器学习成本
Transformer架构自2017年被Vaswani等人提出以来,凭借其核心的注意力机制,已成为AI领域的重大突破。该机制允许模型根据任务需求灵活聚焦于输入的不同部分,极大地增强了对复杂语言和结构的理解能力。起初主要应用于自然语言处理,Transformer迅速扩展至语音识别、计算机视觉等多领域,展现出强大的跨学科应用潜力。然而,随着模型规模的增长,注意力层的高计算复杂度成为发展瓶颈。为此,本文探讨了在PyTorch生态系统中优化注意力层的各种技术,
1006 6
优化注意力层提升 Transformer 模型效率:通过改进注意力机制降低机器学习成本
|
机器学习/深度学习 算法 数据挖掘
算法金 | K-均值、层次、DBSCAN聚类方法解析
**摘要:** 这篇文章介绍了聚类分析的基本概念和几种主要的聚类算法。聚类是无监督学习中用于发现数据内在结构的技术,常用于市场分析、图像分割等场景。K-均值是一种基于划分的算法,简单高效但易受初始值影响;层次聚类包括凝聚和分裂方式,形成层次结构但计算复杂;DBSCAN基于密度,能处理任意形状的簇,但参数选择敏感。文章还讨论了这些算法的优缺点和适用场景,并提供了相关资源链接和Python实现。
1270 9
算法金 | K-均值、层次、DBSCAN聚类方法解析
|
人工智能 算法 搜索推荐
云端问道11期方案教学-创建专属AI助手-阿里云百炼产品能力分享
阿里云百炼产品能力分享旨在帮助用户深入了解百炼的核心功能,并快速将大模型与系统结合。主要内容包括:1. 百炼的产品定位和能力简介,涵盖模型推理、应用搭建等;2. 知识检索RAG智能体的应用能力和优势,介绍其高效构建知识库的步骤及常见问题;3. 最佳落地案例实践,如宠物行业AI助手和产业分析类互联网企业的Copilot机器人。通过这些内容,用户可以全面掌握百炼在实际业务中的应用方法和效果。
584 0
|
存储 固态存储 Windows
|
设计模式 消息中间件 缓存
DDD系列第五讲:聊聊如何避免写流水账代码
在过去一年里我们团队做了大量的老系统重构和迁移,其中有大量的代码属于流水账代码,通常能看到是开发在对外的API接口里直接写业务逻辑代码,或者在一个服务里大量的堆接口,导致业务逻辑实际无法收敛,接口复用性比较差。所以这讲主要想系统性的解释一下如何通过DDD的重构,将原有的流水账代码改造为逻辑清晰、职责分明的模块。
11618 3
DDD系列第五讲:聊聊如何避免写流水账代码

热门文章

最新文章