WEEX
Weex 是使用流行的 Web 开发体验来开发高性能原生应用的框架。
Weex 致力于使开发者能基于通用跨平台的 Web 开发语言和开发经验,来构建 Android、iOS 和 Web 应用。简单来说,在集成了 WeexSDK 之后,你可以使用 JavaScript 语言和前端开发经验来开发移动应用。
Weex 渲染引擎与 DSL 语法层是分开的,Weex 并不强依赖任何特定的前端框架。目前 Vue.js 和 Rax 这两个前端框架被广泛应用于 Weex 页面开发,同时 Weex 也对这两个前端框架提供了最完善的支持。
Vue && Vue Native
Vue是什么
https://cn.vuejs.org/v2/guide/
Vue是一个前端框架,且Vue 的核心库只关注视图层,结合Node.js进行开发
Weex在迭代的过程中选择了于Vue2.0,因为该版本的Vue加入了 Virtual-DOM 和预编译器的设计,使得该框架在运行时能够脱离 HTML 和 CSS 解析,只依赖 JavaScript,如此,Vue在和WEEX合作后,便获得了使用JS预编译原生的组件UI的能力。
同React Native一样,有人也将WEEX叫做Vue Native。
Vue开发示例代码
<template>
<div class="wrapper">
<text class="iconfont"></text>
<home-header></home-header>
<scroller class="main-list" offset-accuracy="300px">
<refresher></refresher>
<div class="cell-button" @click="jumpWeb('https://m.you.163.com')">
<yx-slider :imageList="YXBanners" ></yx-slider>
</div>
<div class="cell-button">
<block-1 :title="block1.title" :items="block1.items"></block-1>
</div>
</scroller>
</div>
</template>
<style scoped>
.iconfont { font-family:iconfont; }
.main-list{ position: fixed; top: 168px; bottom: 90px; left: 0; right: 0; }
</style>
<script>
var navigator = weex.requireModule('navigator');
import util from '../../src/assets/util';
import Header from '../components/Header.vue';
import refresher from '../components/refresh.vue';
import YXSlider from '../components/YXSlider.vue';
import Block1 from '../components/Block1.vue';
export default {
components: {
'home-header': Header,
'refresher': refresher,
'yx-slider': YXSlider,
'block-1': Block1
},
data () {
return {
YXBanners: [
{ title: '', src: 'http://doc.zwwill.com/yanxuan/imgs/banner-1.jpg'},
{ title: '', src: 'http://doc.zwwill.com/yanxuan/imgs/banner-2.jpg'},
{ title: '', src: 'http://doc.zwwill.com/yanxuan/imgs/banner-3.jpg'}
]
}
},
methods: {
jumpWeb (_url) {
const url = this.$getConfig().bundleUrl;
navigator.push({
url: util.setBundleUrl(url, 'page/web.js?weburl='+_url) ,
animated: "true"
});
}
}
}
</script>
打包
熟悉RN的人都知道,RN的发布实际上就是发布一个JSBundle,Weex也是这样,但不同的是,Weex将工程进行分包,发布多个JSBundle。因为weex是单页独立开发的,每个页面都将通过weex打包器将vue/we页面打包成一个单独的JSBundle,这样的好处在于减少单个bundle包的大小,使其变的足够小巧轻量,提高增量更新的效率。
# 仅打包
$ npm run build
# 打包+构建
$ weex build ios
# 打包+构建+安装执行
$ weex run ios
以上三种均会触发weex对工程进行打包。在我们执行了以上打包命令后,所有的工程文件将被单独打成一个独立的JSBundle,如下:
发包
打包后的 JSBundle 一般发布到发包服务器上,客户端从服务器更新包后即可在下次启动执行新的版本,而无需重新下载 app,因为运行依赖的 WeexSDK 已经存在于客户端了,除非新包依赖于新的 SDK,这也是热更新的基本原理。
Weex SDK
【WeexSDK】包括
【JS Framework】JSBundle 的执行环境
【JS-Native Bridge】中间件或者叫通讯桥梁,也叫【Weex Runtime】
【Native Render Engine】解析 js 端发出的指令做原生控件布局渲染
执行
Weex 的 iOS 和 Android 客户端的【JSFramework】中都会运行一个 JavaScript 引擎,来执行 JS bundle,同时向各端的渲染层发送规范化的指令,调度客户端的渲染和其它各种能力。iOS 下选择了 JavaScriptCore 内核,而在 Android 下选择了 UC 提供的 v8 内核(RN两端都是JavaScriptCore 内核)。
JSBundle被push到客户端后就会在JSFramework中执行,最终输出三端可读性的VNode节点,数据结构简化如下:
{
tag: 'div',
data: {
staticStyle: { justifyContent: 'center' }
},
children: [{
tag: 'text',
data: {
staticClass: 'txt'
},
context: {
$options: {
style: {
freestyle: {
textAlign: 'center',
fontSize: 200
}
}
}
},
children: [{
tag: '',
text: '文字'
}]
}]
}
有了统一的VNode节点,各端即可根据自己的方法解析渲染原生UI了,之前的所有操作都是一致的,包括文件格式、打包编译过程、模板指令、组件的生命周期、数据绑定等。
然而由于目标执行环境不同(浏览器和 Weex 容器),在渲染真实原生UI的时候调用的接口也不同。
此过程发生在【Weex SDK】的【Weex Runtime】中。
最总【Weex Runtime】发起渲染指令callNative({…})有RenderEngine完成渲染
Weex框架模型及运行时模型
weex文件分包打包成单个JSBundle文件
发布到发包服务器上,通过热更新push到用户的客户端,交由【Weex SDK】执行解析
SDK中的【JS Framework】执行Bundle脚本生成Virtual DOM
Virtual DOM经由各端执行环境【Weex Runtime】解析翻译成执行指令
【Native RenderEngine】接收到指令后执行渲染操作,作出渲染出完整的界面
Weex工程模型官方图
Weex模型扩充图
拓展 - Weex的三种渲染模式
-
全页模式
单页使用或整个App使用Weex开发(还不完善,需要开发Router和生命周期管理)。
使用Weex开发整个App,期间触碰到Weex的在此模式下诸多不足,如StatusBar控制、Tab切换、开场动画自定义、3DTouch、 Widget等等原生的特色功能没有现成的API,需要我们自己扩展,甚至扩展不了。因此并不能完全“灭掉”原生。 -
Native Component模式
把Weex当作一个iOS/Android组件来使用,类比ImageView。
这类需求遍布手淘主链路,如首页、主搜结果、交易组件化等,这类Native页面主体已经很稳定,但是局部动态化需求旺盛导致频繁发版,解决这类问题也是Weex的重点。 -
H5 Component模式
在H5种使用Weex,类比WVC。一些较复杂或特殊的H5页面短期内无法完全转为Weex全页模式(或RN),比如互动类页面、一些复杂频道页等。这个痛点的解决办法是:在现有的H5页面上做微调,引入Native解决长列表内存暴增、滚动不流畅、动画/手势体验差等问题。
另外,WVC将会融入到Weex中,成为Weex的H5 Components模式。