Weex是由阿里巴巴研发的一套移动跨平台技术框架,研发的初衷是为了解决移动开发过程当中频繁发版和多端研发的问题。使用Weex提供的跨平台技术,开发者能够很方便的使用Web技术来构建高性能、可扩展的Native级别的性能体验,并支持在Android、iOS、YunOS和Web等多平台上进行部署。具体的说,当在项目中集成WeexSDK以后,就可使用JavaScript和现代流行的前端框架来开发移动应用。html
同时,Weex框架的结构是解耦的,渲染引擎与语法层是分开的,也不依赖任何特定的前端框架,目前主要支持Vue.js和Rax两个前端框架。这样一来,甚至可使用其余前端框架来驱动Weex,打造三端一致的Native应用。前端
WeexBox是Weex的脚手架开发框架,和著名的WeexEros和WeexPlus的做用同样。相比Weex,WeexBox具备以下的特色:vue
借助weexbox提供的cli工具,咱们能够快速的初始化工程项目。android
# 安装
cnpm i -g @weexbox/cli
# 新建一个weex工程
weexbox create projectName
# 进入工程
cd projectName
# 安装依赖
cnpm i
复制代码
初始化的项目里已经内置了 @weexbox/debugger工具,它负责调试功能。ios
注意:确保电脑与手机处于同一网段。git
调试app时,须要在weex项目中运行以下命令:es6
npm run debug
复制代码
若是要单独调试某个页面,WeexBox也是支持的。github
npm run debug [vue/weex页面的路径]
复制代码
打开app的调试扫码工具,扫二维码使pc与移动终端创建链接。 此时右上角有另一个二维码,点开并扫描这个二维码便可将这个JSbundle页面载入真机渲染成原生页面。 web
同时,WeexBox初始化的项目里已经内置了 @weexbox/builder,它负责打包功能。vue-router
#编译开发环境
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。
修改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 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>
复制代码
若是从bundle中加载图片,src 以bundle://开头,例如:
<image src="bundle://image.png"></image>
复制代码
若是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>
复制代码
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)