WeexBox 快速上手
概述
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)