共计 7231 个字符,预计需要花费 19 分钟才能阅读完成。
概述
Weex 是由阿里巴巴研发的一套移动跨平台技术框架,研发的初衷是为了解决移动开发过程中频繁发版和多端研发的问题。使用 Weex 提供的跨平台技术,开发者可以很方便的使用 Web 技术来构建高性能、可扩展的 Native 级别的性能体验,并支持在 Android、iOS、YunOS 和 Web 等多平台上进行部署。具体的说,当在项目中集成 WeexSDK 之后,就可以使用 JavaScript 和现代流行的前端框架来开发移动应用。
同时,Weex 框架的结构是解耦的,渲染引擎与语法层是分开的,也不依赖任何特定的前端框架,目前主要支持 Vue.js 和 Rax 两个前端框架。这样一来,甚至可以使用其他前端框架来驱动 Weex,打造三端一致的 Native 应用。
WeexBox 是 Weex 的脚手架开发框架,和著名的 WeexEros 和 WeexPlus 的作用一样。相比 Weex,WeexBox 具有如下的特点:
零配置,开箱即用的项目,自带最佳实践;
无需安装 weex-toolkit;
比 weex-debugger、weex-builder 更快的构建速度;
支持 sass、es6、file-loader、uglify、eslint 等;
可通过审核的热更新,静默模式和强制模式随意切换;
N 多实用的 Module 扩展;
快速上手
支持的系统
Android 5.0 (API 21)+
iOS 10.0+
开发环境
Node:Nodejs 8.0+
AndroidStudio(仅限 Android):AndroidStudio 3.0+
Xcode(仅限 iOS):Xcode 10.0+
CocoaPods(仅限 iOS):CocoaPods 1.5.0+
创建项目
借助 weexbox 提供的 cli 工具,我们可以快速的初始化工程项目。
# 安装
cnpm i -g @weexbox/cli
# 新建一个 weex 工程
weexbox create projectName
# 进入工程
cd projectName
# 安装依赖
cnpm i
初始化的项目里已经内置了 @weexbox/debugger 工具,它负责调试功能。
调试
注意:确保电脑与手机处于同一网段。
调试真机 JSbundle
调试 app 时,需要在 weex 项目中运行如下命令:
npm run debug
此时会自动打开 web,打开 app 的调试扫码工具扫二维码使 pc 与移动终端建立连接,当你看到类似以下这张图,就表示连接成功了。
调试开发页面
如果要单独调试某个页面,WeexBox 也是支持的。
npm run debug [vue/weex 页面的路径]
打开 app 的调试扫码工具, 扫二维码使 pc 与移动终端建立连接。此时右上角有另外一个二维码,点开并扫描这个二维码即可将这个 JSbundle 页面载入真机渲染成原生页面。
打包
同时,WeexBox 初始化的项目里已经内置了 @weexbox/builder,它负责打包功能。
#编译开发环境
npm run develop
# 编译测试环境
npm run test
# 编译准生产环境
npm run preRelease
# 编译生成环境
npm run release
项目结构
.
├── config // 配置文件夹
│ ├── update-config.json // 热更新的配置文件
│ └── weexbox-config.js // 图片资源的配置文件
├── deploy // 输出文件夹
├── platforms // 原生文件夹
│ ├── android // Android 工程
│ └── ios // iOS 工程
├── src // vue 源码文件夹
│ └── module // 模块文件夹
│ └── page // 页面文件夹
│ ├── App.vue // vue 源码
│ └── index.js // 入口文件
└── static // 图片资源文件夹
使用 npm i 命令安装依赖后,项目的结构如上。项目同时也搭建了 app 的基础架构:在工程 platforms 文件夹中,会看到两个文件夹 android、ios,Android 端使用 Android Studio 开发工具,导入 platforms/android 文件夹,构建打包生成项目的 apk;iOS 端使用 Xcode 开发工具,导入 platforms/ios 文件夹,构建打包生成项目的 ipa。
iOS 集成 WeexBox
集成 SDK
修改 Podfile 文件,添加 WeexBox 依赖:
source ‘https://github.com/cocoapods/specs.git’
platform :ios, ‘10.0’
inhibit_all_warnings!
use_modular_headers!
target ‘WeexBoxExample’ do
pod ‘WeexBox’
end
初始化
在 AppDelegate.swift 中添加如下代码:
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?)
-> Bool {
// 初始化 WeexBox
WeexBoxEngine.setup()
// 开启调试
WeexBoxEngine.isDebug = true
window = UIWindow(frame: UIScreen.main.bounds)
window?.backgroundColor = .white
// 使用 WBNavigationController 作为导航基类
window?.rootViewController = WBNavigationController(rootViewController: LaunchController())
window?.makeKeyAndVisible()
return true
}
事件通知
WeexBox 提供了原生与 weex 互相通知的能力,可以用作原生之间的通知。主要借助 Event 来实现:
// 注册事件
Event.register()
// 发送事件
Event.emit()
// 注销事件
Event.unregister()
// 注销所有事件
Event.unregisterAll()
网络
Network 类封装了 Alamofire,原生和 weex 的网络请求都会走这里。
// 网络请求域名
Network.server = 你的网络请求域名
// 发起网络请求。如果 url 已经包含了域名,会忽略你上面的设置
Network.request(url)
说明:原生也可以直接使用 Alamofire,如果是这样,建议使用 Network 提供的 sessionManager。大多数情况下 app 会有自己的网络封装,可以参考 weexbox 来实现自己的 network module。
热更新
// 配置热更新地址
UpdateManager.serverUrl = hotdeployUrl
// 是否需要强制更新
UpdateManager.forceUpdate = true
// 执行热更新
UpdateManager.update {(state, progress, error, url) in
switch state {
case .Unzip:
// 解压
case .DownloadFile:
// 下载
case .UpdateSuccess:
// 更新成功,可以进入 APP
// 如果开启了强制更新,会等到下载完成才会进入这里。否则就是静默更新,解压成功就会进入
}
}
路由
路由提供页面间的跳转功能。前端的路由可以参考:vue-router。
注册路由
Router.register()
说明:WeexBox 默认注册了 weex 和 web,你可以在 app 初始化的时候重新注册,用你自己的 VC 覆盖它们。
路由实例的属性
// 页面名称
public var name: String = “”
// 下一个 weex/web 的路径
public var url: String?
// 页面出现方式:push, present
public var type: String = Router.typePush
// 是否隐藏导航栏
public var navBarHidden: Bool = false
// 需要传到下一个页面的数据
public var params: Dictionary<String, Any>?
// 打开页面的同时关闭页面
public var closeFrom: Int?
// 关闭页面的方向,默认和堆栈方向一致
public var closeFromBottomToTop = true
// 关闭页面的个数
public var closeCount: Int?
打开页面
var router = Router()
// 原生页面
router.name = “ 你注册路由时的页面名称 ”
// weex 页面
router.name = Router.nameWeex
router.url = “module/page.js”
// web 页面
router.name = Router.nameWeb
router.url = “https://aygtech.github.io/weexbox”
router.open()
关闭页面
var router = Router()
router.close()
Android 集成 WeexBox
Android SDK 使用 Kotlin 开发,并且 100% 兼容 Java。对于有追求的团队而言,强烈建议使用 Kotlin 来开发,开发速度和稳健度都会大幅提升!
初始化
在 Android 的 Application 中初始化 WeexBox SDK。
override fun onCreate() {
super.onCreate()
// 初始化 WeexBox
WeexBoxEngine.setup(this, null)
// 开启调试
WeexBoxEngine.isDebug = true
}
事件通知
WeexBox 提供了原生与 weex 互相通知的能力,你可以将它用作原生之间的通知,不管是 weex 界面还是原生界面,只要注册了事件,都能接收到。
通过 Event 类,你可以在 weex 发送事件与注册事件:
// 注册事件
Event.register()
// 发送事件
Event.emit()
// 注销事件
Event.unregister()
// 注销所有事件
Event.unregisterAll()
也可以 在原生代码中发送事件与注册事件。
// 注册事件
Event.register(this,”YourEventName”) {//this 为 Activity 或者 Fragment
//var value = it!![“key”] it 为发送事件传过来的 Map<String,Any>,可不传
}
// 发送事件
Map<String, Object> map = new HashMap<>()
map.put(“key”, Object)
Event.emit(“YourEventName”, map)//map 可为 null
// 注销事件
Event.unregister(this, “YourEventName”) //this 为 Activity 或者 Fragment
// 注销所有事件
Event.unregisterAll(this)
网络
WeexBox 的网络使用的是 Retrofit 的二次封装。原生和 weex 的网络请求都会走这里。
// 网络请求域名
Network.server = 你的网络请求域名
// 发起网络请求。如果 url 已经包含了域名,会忽略你上面的设置
Network.request(url)
热更新
// 配置热更新地址
UpdateManager.serverUrl = hotdeployUrl
// 是否需要强制更新
UpdateManager.forceUpdate = true
// 执行热更新
UpdateManager.update {state, progress, error, url ->
when (updateState) {
UpdateManager.UpdateState.Unzip -> // 解压
UpdateManager.UpdateState.DownloadFile -> // 下载
UpdateManager.UpdateState.UpdateSuccess -> {
// 更新成功,可以进入 APP
// 如果开启了强制更新,会等到下载完成才会进入这里。否则就是静默更新,解压成功就会进入
… // 还有各种状态码,参见下面表格,可以处理热更新各种情况,如热更新失败提示用户重启
}
}
}
UpdateManager 返回的状态有:
状态码
描述
Unzip
解压文件
UnzipError
解压文件出错
UnzipSuccess
解压文件成功
GetServer
获取服务器路径
GetServerError
获取服务器路径出错
DownloadConfig
下载配置文件
DownloadConfigError
下载配置文件出错
DownloadConfigSuccess
下载配置文件成功
DownloadMd5
下载 md5 文件
DownloadMd5Error
下载 Md5 出错
DownloadMd5Success
下载 md5 文件成功
DownloadFile
下载文件
DownloadFileError
下载文件出错
DownloadFileSuccess
下载文件成功
UpdateSuccess
更新成功
路由
注册路由
Router.register()
说明:WeexBox 默认注册了 weex 和 web,你可以在 app 初始化的时候重新注册,用你自己的 VC 覆盖它们。
路由实例的属性
// 页面名称
public var name: String = “”
// 下一个 weex/web 的路径
public var url: String?
// 页面出现方式:push, present
public var type: String = Router.typePush
// 是否隐藏导航栏
public var navBarHidden: Bool = false
// 需要传到下一个页面的数据
public var params: Dictionary<String, Any>?
// 打开页面的同时关闭页面
public var closeFrom: Int?
// 关闭页面的方向,默认和堆栈方向一致
public var closeFromBottomToTop = true
// 关闭页面的个数
public var closeCount: Int?
打开页面
var router = Router()
// 原生页面
router.name = “ 你注册路由时的页面名称 ”
// weex 页面
router.name = Router.nameWeex
router.url = “module/page.js”
// web 页面
router.name = Router.nameWeb
router.url = “https://aygtech.github.io/weexbox”
router.open()
关闭页面
var router = Router()
router.close()
静态资源
图片加载
weexbox 支持 3 种图片加载方式:
网络加载
网络加载图片时,src 以 http 开头,例如:
<image src=”https://aygtech.github.io/weexbox/logo.png”></image>
从 APP bundle 中加载
如果从 bundle 中加载图片,src 以 bundle:// 开头,例如:
<image src=”bundle://image.png”></image>
从 APP 文件中加载
如果 src 不以上面两种方式开头,还可以从文件中加载,例如:
// iOS
<image src=”file://var/mobile/Media/DCIM/100APPLE/IMG_0171.PNG”></image>
// Android
<image src=”/storage/emulated/0/DCIM/Camera/IMG_20180917_145836.jpg”></image>
modal
WeexBox 内置了一些模块,但是这些模块相比其他的,如 WeexEros 和 WeexPlus 来说是明显偏少的。为此,你可以使用 Weex 提供的扩展机制来扩展自己的 modal,相关内容可以参考:Weex 快速上手
除了常见的:alert、confirm 外,还延伸了一些更频繁使用的 api,eg:actionSheet(操作表弹框)、showLoading(显示菊花)等,更加常态化、大众化以及多元化。
实现的示例代码如下:
# 引用
const modal = weex.requireModule(‘wb-modal’)
# 警告弹框
modal.alert({
title: ‘ 标题 ’,
message: ‘ 弹窗内容 ’,
okTitle: ‘ 确定 ’
}, (result) => {
})
// callback 参数
result: {
status: 0
}
如果要打开外部的 Module,需要使用 wb-external。例如:
# 引用
const external = weex.requireModule(‘wb-external’)
# 调用摄像头拍照,实现图片裁剪上传
external.openCamera({
// 能否剪裁
enableCrop: true,
// 是否矩形剪裁,true 为圆形剪裁
isCircle: true,
// 宽度
width: 100,
// 高度
height:100
}, (result) => {
})
// callback 参数
result: {
status: 0,
error: ”,
data: {
// 图片的存储路径
url: ‘/docment/123.png’
更多的模块可以参考:传送门
目前,大前端开发的趋势越来越明显,与 Weex 同一技术系的 RN 早已声名远播,Weex 作为后期之秀,目前还在不断的追赶和优化中虽然有各种 bug 被人诟病,但是,哪个优秀的技术发展没有经历这样的过程呢。“不经一番寒彻骨,怎得梅花扑鼻香”,相信通过大家的无私奉献,Weex 社区也会变得越来越好。
本人正在完成《Weex 跨平台开发实战》一书,有任何好的建议的可以留言,也欢迎大家踊跃提意见。(群:515980159)