混合开发 weex 跨平台
目录
混合开发 weex 跨平台
Weex 是一个可以使用现代化的 Web 技术开发高性能原生应用的框架。
- 官网
- 使用指南
- Online Editor
- Playground:Weex 示例 App,可扫码预览 Weex 代码构建后的页面
简介
Weex 致力于使开发者能基于通用跨平台的 Web 开发语言和开发经验,来构建 Android
、iOS
和 Web
应用。简单来说,在集成了 WeexSDK
之后,你可以使用 JavaScript
语言和前端开发经验来开发移动应用。
在开发阶段,一个 Weex 页面就像开发普通网页一样;在运行时,Weex 页面又充分利用了各种操作系统的原生组件和能力。
高性能
:Weex 使用原生组件和原生模块,来最大化利用原生渲染的性能优势以及平台能力,所有的组件和模块都是可插拔、可扩展的。跨平台
:你可以使用同一份代码编译成不同目标文件分别在 Web、Android 和 iOS 平台上运行。原生的组件和模块在不同平台中有不同的实现,但是它们都提供了相同的接口。贴近前端生态
:Weex 拥抱已有的 Web 生态,你可以使用现代化的前端技术开发移动应用。 Weex 支持了最常用 CSS 样式以及最流行的前端框架,如 Vue 和 Rax,在未来或许还可以支持更多。
Weex并不是一个前端框架。实际上,前端框架仅仅是 Weex 的语法层
或称之为 DSL
(Domain-specific Language),它们与原生渲染引擎
是分离的。换句话说,Weex 并不依赖于特定的前端框架,随着前端技术的发展,Weex 也可以集成更多广泛使用的前端框架。
第一个项目
开发环境配置
- 安装
Node.js
和npm
包管理工具npm -v
- 安装命令行工具 Weex CLI:用来快速创建一个空项目、初始化 iOS 和 Android 开发环境、调试、安装插件等操作
npm i -g weex-toolkit // i 是 install 的缩写,-g 代表全局安装
weex -v
weex help - 初始化 Weex 项目
weex create project_name //在当前目录下创建指定目录,创建一个空的模板项目,源代码在
src/
目录中 - 运行
npm install //安装项目所需依赖。如果在初始化项目时选择了自动安装依赖,可跳过这一步
npm start //会启动一个本地的 web 服务,监听8081
端口 - 默认情况下并不初始化 iOS 和 Android 项目,可以通过如下命令来添加特定平台的项目
weex platform add android/ios
- 启动应用
weex run android/ios/web
- 调试
weex debug //启动一个调试服务,并且在 Chrome 中打开调试页面
集成到 Android 项目
Weex 支持以下 ABI:x86
、armeabi-v7a
、arm64-v8a
- 设置 gradle 依赖:weex_sdk、fastjson、support library
- 配置混淆规则
- 声明权限:网络和SD卡
- 初始化 sdk
- 扩展配置
- 创建
XSDKInstance
,WXSDKInstance 是 weex 渲染页面的基本单元- 通过
instance.render(url)
拉取 bundle - 在 IWXRenderListener 的回调方法
onViewCreated
中返回创建的 view - 将返回的 view 添加到 Activity 的 view 上
- 通过
- 运行 app,您将会看到一个
hello world
页面
最简单的案例
//初始化
InitConfig.Builder builder = new InitConfig.Builder();
WXSDKEngine.initialize(this, builder.build());
<template>
<div style="justify-content:center;">
<text class="freestyle">白乾涛</text>
</div>
</template>
http://dotwe.org/
<style scoped>
.freestyle {
color: #41B883;
text-align: center;
font-size: 233px;
}
</style>
在上面的例子中,
<div>
和<text>
在移动端上渲染出来的都是原生组件,充分利用了操作系统组件的能力与渲染速度。
调试
调试组件 Devtools
Android Devtools for Apache Weex 能够方便调试 Weex 页面
implementation 'com.taobao.android:weex_inspector:0.24.2.11'
//需要引入 okhttp
implementation 'com.squareup.okhttp:okhttp:2.3.0'
implementation 'com.squareup.okhttp:okhttp-ws:2.3.0'
调试命令行 weex-toolkit
npm i -g weex-toolkit // i 是 install 的缩写,-g 代表全局安装
weex -v
weex help
weex debug // 启动调试控制台
如果你有需要编译的页面,也可以通过 weex debug [ folder | file ]
命令进行编译,编译后的页面将会在 页面
这个标签下显示。
开始调试
调试需要使用集成了 Weex 调试工具 Devtools
的 APP 进行扫码调试。
在调试开始前,请确保安装了调试应用的手机与 PC 处于同一局域网下,同时关闭 VPN 等代理设置,否则将无法正常进行调试。同时,我们在使用功能时,尽量保证其他功能为关闭状态,如在使用JS调试
功能时将无关的网络审查
功能关闭,将会有更好的开发体验。
你也可以使用 Weex 官方提供的 Playground App 进行代码调试。
回到调试二维码页面,用应用的扫码功能进行扫码,即可进入调试控制台。
其他调试技巧
- JS 调试:开启 JS 调试功能即可进入 Weex 代码调试模式
- 日志等级:通过控制台及日志等级选项对日志进行筛选过滤,保留你关注的日志内容
- 网络审查:开启网络审查功能可以查看应用的网络请求信息,对页面的请求进行有效的分析
- 节点审查:节点审查模式下会发送大量的页面信息,默认开启,建议复杂页面情况下关闭该功能
- 拓展功能:快速导航、文件替换等拓展功能需在 JS 调试功能开启并且处于 Weex 页面内才可使用
Weex 和 Web 的平台差异
Weex 是一个跨平台解决方案,Web 平台只是其中一种
运行环境,除此之外还可以在 Android 和 iOS 客户端中运行。原生开发平台和 Web 平台之间存在很多差异,在功能和开发体验上都有一些差异。
- Weex 环境中没有 DOM
- 不支持 Web API
- 没有
Element
、Event
、File
等对象 - 不支持选中元素
- 不支持基于 DOM API 的程序库(如 jQuery)
- 有限的事件类型
- Weex 环境中没有 BOM
- 没有
window
、screen
对象 - 不支持使用全局变量
- 如果是想要获取设备的屏幕或环境信息,可以使用
WXEnvironment
变量 - 没有
document
对象 - 没有
history
、location
、navigator
对象
- 没有
- 能够调用移动设备原生 API
- 在 Weex 中能够调用移动设备原生 API,使用方法是通过注册、调用模块来实现
- 内置的模块:如 clipboard(剪切板)、 navigator(导航控制)、storage(本地存储)
- Weex 提供了横向扩展的能力,可以扩展原生模块
Weex 环境变量
每个 Weex 页面的 JS 上下文中都有一个相互独立的 weex
变量,它可以像全局变量
一样使用,不过它在不同页面中是隔离而且只读
的。
Weex 提供了 weex.config.env
和全局的 WXEnvironment
变量(它们是等价的)来获取当前执行环境的信息
这个例子 打印出了 Weex 环境对象中的所有值。
WXEnvironment.setOpenDebugLog(BuildConfig.DEBUG);
WXEnvironment.setApkDebugable(BuildConfig.DEBUG);
Android 功能扩展
Weex 提供了扩展机制,可以根据自己的业务进行定制自己的功能,主要分为:
- Module 扩展:扩展
非 UI
的特定功能,例如 sendHttp、openURL - Component 扩展:实现特别功能的
控件
,例如 RichTextview,RefreshListview - Adapter 扩展:Weex 对一些基础功能实现了统一的
接口
,可实现这些接口来定制自己的业务,例如 图片下载 - JS 全局变量自定义扩展
Module 扩展
public class MyModule extends WXModule {
@JSMethod() // 不加参数时,run ui thread
public void printLog(String msg) {
Toast.makeText(mWXSDKInstance.getContext(), msg, Toast.LENGTH_SHORT).show();
}
@JSMethod(uiThread = false) //run JS thread
public void fireEventSyncCall() {
}
}
- Weex 会根据注解
@JSMethod
来判断当前方法是否是扩展方法,以及当前方法是否要运行在 UI 线程 - 扩展方法仅支持 int, double, float, String, Map, List 类型的参数
- 扩展方法是通过
反射
来调用的,所以 Module 不能被混淆,扩展方法也必须是 public 类型
-keep public class * extends com.taobao.weex.common.WXModule{*;}
使用前必须先注册
WXSDKEngine.registerModule("MyModule", MyModule.class);
JS 调用如下:
<template>
<div>
<text onclick="click">testMyModule</text>
</div>
</template>
<script>
module.exports = {
methods: {
click: function() {
weex.requireModule('MyModule').printLog("I am a weex Module");
}
}
}
</script>
Component 扩展
public class RichText extends WXComponent<TextView> {
public RichText(WXSDKInstance instance, WXVContainer parent, BasicComponentData basicComponentData) {
super(instance, parent, basicComponentData);
}
@Override
protected TextView initComponentHostView(@NonNull Context context) {
TextView textView = new TextView(context);
textView.setTextSize(20);
textView.setTextColor(Color.BLACK);
return textView;
}
@WXComponentProp(name = "tel")
public void setTel(String telNumber) {
getHostView().setText("tel: " + telNumber);
}
}
- Component 扩展的方法必须添加注解
@WXComponentProp(name=value)
- Component 扩展的方法仅支持 int, double, float, String, Map, List 类型的参数
- Component 扩展的方法是通过
反射
来调用的,所以不能被混淆,扩展方法也必须是 public 类型
-keep public class * extends com.taobao.weex.ui.component.WXComponent{*;}
使用前必须先注册
WXSDKEngine.registerComponent("richText", RichText.class);
JS 调用如下:
<template>
<div>
<richText tel="12305" style="width:200;height:100">12305</richText>
</div>
</template>
从 WeexSDK 0.9.5 开始,支持在一个 Component 中他通过
@JSMethod
声明一个组件方法
Adapter 扩展
- WXUserTrackAdapter:打点相关
- IActivityNavBarSetter:
WXNavigatorModule
的实现依赖这个接口,用来操作navigation - IWXStorageAdapter:
WXStorageModule
实现依赖这个接口,用来实现数据的存、取默认使用DefaultWXStorage
实现 - IWXJSExceptionAdapter:WEEX的异常上报接口
ImageAdapter
Weex 和图片库完全解耦,Weex 的图片加载,都是通过调用公共接口,由实现类
决定调用哪个图片库
IWXImgLoaderAdapter
:根据url,load 图片给某个 viewIDrawableLoader
:根据url,load 图片给某个 drawable
public interface IWXImgLoaderAdapter {
void setImage(String url, ImageView view, WXImageQuality quality, WXImageStrategy strategy);
}
WXImageQuality
:图片质量,有LOW
(默认),NORMAL
,HIGH
,ORIGINAL
WXImageStrategy
:扩展类参数,配置图像是否可以剪切isClipping
、锐化isSharpen
以及配置占位符placeHolder
IWXHttpAdapter
Weex 和网络库也是解耦的,通过接口形式调用,由实现类决定调用哪个网络库。
public interface IWXHttpAdapter {
void sendRequest(WXRequest request, OnHttpListener listener);
}
public class WXRequest {
public Map<String, String> paramMap; // 请求参数
public String url; // 目标 url
public String method; // 请求方法 post、get
public String body; //请求体
public int timeoutMs = 3000; // 请求超时时间
public static final int DEFAULT_TIMEOUT_MS = 3000;
public String instanceId; // 页面 id
public WXRequest() {
}
}
public interface IWXHttpAdapter {
void sendRequest(WXRequest var1, IWXHttpAdapter.OnHttpListener var2);
public interface OnHttpListener {
void onHttpStart(); //开始请求
void onHeadersReceived(int statusCode, Map<String, List<String>> headers); //收到http header内容
void onHttpUploadProgress(int uploadProgress); //上传进度
void onHttpResponseProgress(int loadedLength); //接收到的数据长度
void onHttpFinish(WXResponse response); //请求结束
}
}
URIAdapter
默认实现是 DefaultUriAdapter
public interface URIAdapter {
String REQUEST = "request";
String IMAGE = "image";
String FONT = "font";
String VIDEO = "video";
String LINK = "link";
String BUNDLE = "bundle";
String WEB = "web";
String OTHERS = "others";
@NonNull
Uri rewrite(WXSDKInstance instance, String type, Uri uri);
@NonNull
Uri rewrite(String bundleURL, String type, Uri uri);
}
Weex SDK 提供 local
scheme 来访问打包在应用程序中的资源,在 Android 中,image
组件将从 drawable
资源文件夹加载,字体文件将从 asserts
文件夹加载。
Native 和 JS 交互
自定义发送事件
向 JS 环境发送一些事件,比如click
事件
//推荐使用 WXComponent 中的 fireEvent 方法
fireEvent(String type)
fireEvent(String type, Map<String, Object> params)
fireEvent(String type, Map<String, Object> params, Map<String, Object> domChanges)
//WXSDKManager 中定义的 fireEvent 方法均已废弃(相比上面的方法,都是增加了两个参数)
fireEvent(String instanceId, String ref, String type)
instanceId
:使用WXComponent.getInstanceId()
获取ref
:产生事件的组件 id,使用WXComponent.getRef()
获取type
:事件名称,weex 默认事件名称格式为"onXXX",比如OnPullDown
params
:需要发送的一些额外数据,比如click
时 view 大小、点击坐标等等domChanges
:目标组件的属性和样式发生的修改内容
结果回调
JS调用时,有的场景需要返回一些数
public interface JSCallback {
void invoke(Object data);
void invokeAndKeepAlive(Object data);
}
public class WXLocation extends WXModule {
@JSMethod
public void getLocation(JSCallback callback) {
Map<String, String> data = new HashMap<>();
data.put("x", "x");
data.put("y", "y");
callback.invoke(data); //notify once
callback.invokeAndKeepAlive(data); //Continuous connection
}
}
EEUI 框架
EEUI:Everyone Easy User Interface
使用 Vue.js
跨平台开发高质量原生(Android/iOS)应用。
EEUI 是一个基于 WeexSDK 开发的独立完整框架
(EEUI 仅支持 Android、iOS两端,不支持WEB端)。
除了 Weex 原有的组件外,EEUI 还自带了很多实用的组件
、模块
。同时 EEUI 提供完整的插件
市场,在原有的组件、模块不够业务需求时可以通过插件市场来补充更多的业务需求
降级
Weex 在开发过程中,会不断增加新的 feature,但是这些 feature 可能在低版本
上不兼容,此时就可以使用降级
的方式在低版本 App 中以普通 Web 页面的模式来渲染。
在 Weex 里,降级行为是在前端中触发的,由客户端来实现。触发方式是调用客户端提供的 instanceWrap
模块中的 error
方法来实现。传递的参数主要用于区分降级的类型和原因
,与具体业务场景相关,不做强限制。
const instanceWrap = weex.requireModule('instanceWrap')
instanceWrap.error(errorType, errorCode, message)
errorType
:【数字】 错误类型,由前端触发的降级通常约定为1
errorCode
:【数字】 错误代码message
:【字符串】 错误信息
2020-12-18
本文来自博客园,作者:白乾涛,转载请注明原文链接:https://www.cnblogs.com/baiqiantao/p/14153847.html