1、Weex的由来
WEEX前身
Weex的前身是WeApp,一个用JSON配置原生UI组件来实现动态化的框架,Weex是WeApp的进化版本,加上ex去掉App,就成了现在这个名字。
与Vue.js的关系
如果对前端有所涉猎的同学会发现,Weex的DSL风格与一个前端的MVVM框架Vue.js比较像,那么它们的关系是什么呢?
Weex由多个关键模块组成,分别是DSL transformer、JS Framework、HTML5/iOS/Android Renderer和工具链 , 其中JS Framework就直接使用了部分来自Vue.JS的代码。不过这种使用也是遵守开源协议的(Vue使用MIT协议,Weex使用Apache协议),Weex团队在源码的说明文件中记录了来自Vue.JS和其他开源项目的贡献
2、Weex工作原理
1、DSL : weex文件;
2、Virtual DOM (提升性能) :
Virtual DOM 是一个模拟 DOM 树的 JavaScript 对象。 weex使用 Virtual DOM 来渲染 UI,当组件状态state 有更改的时候,weex会自动调用组件的 render 方法重新渲染整个组件的 UI。
weex主要的目标是提供一套不同的, 高效的方案来更新 DOM.不是通过直接把 DOM 变成可变的数据, 而是通过构建 “Virtual DOM”, 虚拟的 DOM, 随后 weex处理真实的 DOM 上的更新来进行模拟相应的更新。
DOM 树上的节点被称为元素, 而 virtual DOM 是完全不同的抽象, 叫做 components,component 的使用在 weex里极为重要, 因为 components 的存在让计算 DOM diff 更高效。
简单的说就是:
当然如果真的这样大面积的操作 DOM,性能会是一个很大的问题,所以 Weex实现了一个虚拟 DOM,组件 DOM 结构就是映射到这个虚拟 DOM 上,weex在这个虚拟 DOM 上实现了一个 diff 算法,当要更新组件的时候,会通过 diff 寻找到要变更的 DOM 节点,再把这个修改更新到浏览器实际的 DOM 节点上,所以实际上不是真的渲染整个 DOM 树。这个虚拟 DOM 是一个纯粹的 JS 数据结构,所以性能会比原生 DOM 快很多。
3、Android RenderEngine 将输入Virtual DOM 转换成输出的android原声控件;
1、后台部署时会将weex文件转换为JSbundle,大家完全不必担心这部分的时间,因为在后台已经转换完成;
2、Native 渲染和 JavaScript 引擎之间的边界放在了 Virtual DOM,两者通过约定 Virtual DOM 来进行通信,而不是 template + data 或是别的边界,确保渲染性能和灵活度的平衡;
3、Weex和native,H5,RN的对比
1.Weex和H5对比
2.Weex和RN对比
1.目前来说RN也在融合Android和iOS实现,提供统一的书写方案,Weex这方面相比之下还是有优势的,RN稍微慢了一步
2.Weex 有 H5 的解决方案,解决了如:分享到外部的问题
3.Weex 目前有效的解决了list比较费内存的情况
4.Weex 的受众更偏向于前端,因为类Vue的型的书写方式,足够简单。RN的解决方案,提供了很多先进的思路,谁能胜出,各家有各家的说法。
3.Weex优势
兼容css和js语法,学习成本低,上手简单。三端公用,可直接对H5页面稍做修改进行使用。支持热更新和降级处理,基于Vue实现了数据的绑定。
4.Weex劣势
并不能兼容所有的css,开发有一定的局限性,设计的时候没考虑cookie,使用cookie的时候会出现问题。基础控件比较少,若想自定义控件需要两端都实现。
4、Weex开发中遇到的问题
1.使用本地图片
<image class = "setBtn" src= 'xcassets:my_setting'/>
- (id<WXImageOperationProtocol>)downloadImageWithURL:(NSString *)url imageFrame:(CGRect)imageFrame userInfo:(NSDictionary *)userInfo completed:(void(^)(UIImage *image, NSError *error, BOOL finished))completedBlock
{
if ([url hasPrefix:@"//"]) {
url = [@"http:" stringByAppendingString:url];
}
if ([url hasPrefix:@"xcassets:"]) {
UIImage *image = [UIImage imageNamed:[url substringFromIndex:9]];
completedBlock(image, nil, YES);
return [WXXCassetsLoaderOperation new];
}
return (id<WXImageOperationProtocol>)[[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:url] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
} completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
if (completedBlock) {
completedBlock(image, error, finished);
}
}];
}
2.list中cell的margin无效
<cell class="Mine_fotter">
<div class="Mine_fotter_div">
<image class="fotter_btn_icon" src="xcassets:my_kefu"/>
<text class="fotter_btn_name">我的客服</text>
</div>
</cell>
将cell的最外层嵌套一个div,对div进行margin操作
3.Weex和Native的交互
#pragma mark - 初始化weex配置
- (void)resignWeex{
[WXAppConfiguration setAppGroup:@"AliApp"];
[WXAppConfiguration setAppName:@"Weex_haojie"];
[WXAppConfiguration setAppVersion:@"1.1.0"];
[WXSDKEngine initSDKEnvironment];
[WXSDKEngine registerModule:@"callNative" withClass:[WXCustomEventModule class]];
[WXSDKEngine registerHandler:[WXImgLoaderDefaultImpl new] withProtocol:@protocol(WXImgLoaderProtocol)];
#ifdef DEBUG
[WXLog setLogLevel:WXLogLevelLog];
#endif
}
将WXCustomEventModule注册为callNative
WX_EXPORT_METHOD(@selector(pushNativeVC::))
/**
跳到原生页面
@param name 跳转的原生类名
@param params 参数
*/
- (void)pushNativeVC:(NSString *)name :(id)params{
[self pushToViewController:@"JRSettingController" :params];
}
实现并注册方法pushNativeVC::
//注册
const app = weex.requireModule('callNative');
//调用
app.pushNativeVC(methodName);
4.元素的显示隐藏
<div class="bottomAlert" v-if="isHaojie">
<text class = 'bottomAlertTitle'>{{bottomAlertMsg}}</text>
</div>
因为weex没有兼容v-show和display:none的属性,所以要实现元素的显示隐藏要使用v-if,其值为bool值
5.类选择器
<div v-for="item in topArray" :class="[loginState?'TopLoginItem':'TopItem']" @click="jump(item.url)">
<image class="topitemIcon" :src="item.icon" />
<text class="topitemTitle">{{item.title}}</text>
</div>
和vue语法不同,其格式为:class="[loginState?'TopLoginItem':'TopItem']"
6.视图的生命周期 willAppear,willDisAppear
//js代码
<div class="body" @viewappear="onViewappear">
</div>
//ios代码
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self updateInstanceState:WeexInstanceAppear];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[self updateInstanceState:WeexInstanceDisappear];
}
- (void)updateInstanceState:(WXState)state
{
if (_instance && _instance.state != state) {
_instance.state = state;
if (state == WeexInstanceAppear) {
[[WXSDKManager bridgeMgr] fireEvent:_instance.instanceId ref:WX_SDK_ROOT_REF type:@"viewappear" params:nil domChanges:nil];
}
else if (state == WeexInstanceDisappear) {
[[WXSDKManager bridgeMgr] fireEvent:_instance.instanceId ref:WX_SDK_ROOT_REF type:@"viewdisappear" params:nil domChanges:nil];
}
}
}
5、总结
如果考虑三端,可以尝试Weex开发
如果已经有大量实践Vue,也可以尝试Weex开发
对渲染UI的流畅度有较高的期望又想能支持热更新,也可以尝试Weex开发