Weex原理之带你去蹲坑

 本篇将节操满满的安利Weex(˶‾᷄ ⁻̫ ‾᷅˵),不同的角度推荐你入坑,官网有的咱们不拖泥,这里将给你补充官方没有的,深刻到蹲坑给你排忧解难,总会给你点惊喜,内容越后越干,请紧张的往下看。css

两个字,讲究

***** 本文配套,超完整 Weex 项目推荐 : GSYGithubAppWeex ***** html

1、简介

 有对比才有伤害,说到Weex,不免让人联系React Native。虽同为跨平台移动端解决方案,拥JavaScript妄一统天下,单二者的设计理念其实大相径庭。前端

 这里先介绍下二者的差别,给徘徊在 React Native 和 Weex 之间的人,理解更适合哪些场景。vue

类型 React Native Weex
性能 较好 较弱
上手难度 稍高 容易
核心理念 React Vue
框架程度 较重 较轻
特色 适合开发总体App 适合单页面
社区 丰富,Facebook维护 略残念,目前托管apache
支持 Android、IOS Android、IOS、Web
适应性 原生开学习成本低 Web开发学习成本低
JS引擎 JSCore V8

 做为两个框架的深度体验者,我的总结出上面的对比,其中能够看出:node

  • React Native更适合开发完整的App,由于它的性能较好,第三方插件丰富,社群活跃而且维护较好,文档完整等(本篇主角是Weex好吧魂淡(#゚Д゚))。react

  • Weex更适合开发单页面集成,这也是阿里的业务特性。 固然Weex也能够开发完整的多页面App,同时我也是这么用过,不过效果对比React Native,显然强差人意。android

  • Weex胜在容易上手,基于Vue的设计模式,类MVVM的实现,也让前端能更无缝的实现一些高性能的App业务。webpack

  • Weex兼容Android、IOS、Web三端,在单页面的实现上,它有着React Native没法睥睨的先天优点。ios

  • Weex的社群,我的以为仍是弱,资料不足,文档简单,第三方支持太弱。和React Native同样支持带原生功能的插件开发,可是,支持太少了,这也提升了后期的开发门槛。同时,一个小问题很容易让入初学者,三过门而不入,做为一个发布了两年的框架,仍是比较让人吐槽的。git

这就是,所谓的前言吧

2、原理

 这里简要说明下Weex在android下的分层以及原理。

 Weex主要包括三大部分:JS BridgeRenderDom,分别对应WXBridgeManagerWXRenderManagerWXDomManager 。经过WXSDKManager统一管理。其中JS BridgeDom运行在独立的HandlerThread中,而Render运行在UI线程。JS Bridge主要用来和 JS 端实现进行双向通讯,好比把js端的dom结构传递给Dom线程。Dom主要是用于负责dom的解析、映射、添加等等的操做,最后通知UI线程更新。而Render负责在UI线程中对dom实现渲染。

 以下图,是生成dom,dom的解析,映射,添加,渲染的流程。

图片来自网络

 如上可知,由于JS端运行于独立的单线程中,因此为了保证运行的流畅性,通常须要避免在JS端执行耗时操做,好比:网络请求,图片加载等,其实都是在原生端完成,js端执行的是发起一个请求和响应一个结果。同时由于原生端与JS端是经过JS Bridge通信,因此也须要尽可能避免大数据和频繁的通信,致使响应的延迟。

 原生端的dom的加载解析映射,也是性能的一大瓶颈。通常而言,Weex在Web端生成的,是经过webpack的webConfig打包成单页面的index.web.js文件;而在原生端,通常会经过webpack的weexEntry配置成多页面形式:即每个须要独立的.vue的页面,最终会被打包成一个.js文件。因此打开每一个页面时加载对应的js文件,这很好的减少了须要加载的文件大小,提升了dom的解析效率。最后,Weex默认打的js只包含业务js代码,基础js库已经被包含在weex sdk中,也使得体积会小不少。

3、入门

一、配置环境

 程序员就要从配置环开始,Weex 环境搭建 ,点击连接,只要你要一个稳定的网络,参考官网搭建环境,也就一杯茶的功夫,take it easy。配置好以后,weex create testProject建立一个项目High起来吧。

二、快速入门

 weex的入门仍是比较简单的,JavaScript、Vue了解下,便可预定的hello world。

 原生开发也许对vue接触很少,跨界有时候很容易望而却步,其实Vue自己,就是容易上手的框架,相似MVVM的模式(相似Android的DataBinding),很容让人理解上手,简单的说,你只关心数据,而后绑定到显示的控件,就是这么简单。

 通常经过 Vue官网 教程,30分快速撸一发,以后你就直接入门Weex了,对,Weex作的最完全的就是,你直接使用 vue 写一个Web页面,以后再顺手编译成了 ios 和 android 的原生页面(尽管有些时候你须要在平台适配上花费心思)。

请忽略那个this,真的( ̄. ̄)

 如上图(请忽略那个this( ̄. ̄)),这就是一个极度简化的,用Vue写的Weex页面。效果是从显示Hello World ,一秒变I’m CarGuo,就是这么自信。

 在<template>中排布须要渲染的控件,在<style>中指定控件的样式(固然你也能够直接在<template>中),在<script>中写数据获取和处理逻辑等,是否是很简单, Don’t be shy,Let's fuck it !

 由于须要支持三端,Weex在Vue的基础上阉割了一些标签、css样式和事件,具体可见与 Web 平台的差别

 其中,在Android和IOS上,<text> <image>等标签,实际上是被编译为原生控件,这就是上面所说的dom解析,同时你也能够在原生端,自定义控件或者功能模块,而后注册到weex中使用,实际上weex提供的基础控件和功能模块并很少,但却很容易拓展,具体可见 拓展原生端功能

(ps 也不知道阿里是怕作多错多,仍是懒)

 说到这里,就须要说一说Weex的原生插件开发支持,这也是官方文档比较没整理好的缘由,其实文档是有的:Weex插件开发文档,如Android插件大体流程就是:

  • weex plugin create命令建立插件。
  • 在android目录的library下经过@WeexComponent(控件)、@WeexModule(非UI功能)、@WeexAdapter(weex继承功能拓展)实现第三方支持。
  • 将library发布到maven (固然你也能够直接源码发布到npm)
  • 配置根目录的package.json而后发布到npm

 因而可知,weex能够很方便的提供原生功能的拓展支持,可是因为社群较为薄弱,致使第三方插件缺失,有(hen)些(duo)时候你可能不得不本身着手,开发原生端的功能支持,这就对于跨平台开发而言,特别前端开发而言,就稍(te)显(bie)不友好了。

目瞪狗带

题外话 :说到跨平台开发,也许你据说过cordova这位老大哥,它曾是早期的跨平台开发潮流,cordova提供丰富的原生插件和打包功能:经过webview把前端页面打包成一个App,经过插件提供前端须要的原生接口,交互经过webview的js接口支持。为何提及它呢,是由于Weex中,你能够看到不少cordova的影子,相似weex platform add androidweex plugin add xxx都有些cordova的味道。以下图,你现在依旧能够在Weex中找,寻找到cordova的存在感。

cordova残留

三、其余推荐
Vuex 和 Vue-Router ,居家旅行必不可少。
  • Vuex相似Redux,若是你没据说Redux没关系,也不要怂,简单了说,Vuex就是单页面下,帮你管理数据的框架。数据都存在Vuex的store中,你操做store更新数据,而后将store绑定到界面。它的用处在于能够在多个vue组件间,方便的同步数据,更新界面。

  • Vue-Router也是用于单页面下,指定跳到某个页面的管理工具,路由嘛,浅显易懂。

iconfont :矢量图标,少不了iconfont,经过字库生成图标,资源丰富,绝对值得推荐。
weex-ui: weex中可贵的良心官方封装库。
eros :eros 不是框架,是基于 weex 封装、面向前端的 vue 写法的一整套 APP 开源解决方案,是由本木医疗大前端团队通过大量实践沉淀而出。。

4、深刻填坑

一、ES六、ES7

  说到 Javascript ,ES六、ES7必须了解下。Weex中默认就有对其支持,可是对于async、await等,还须要以下一些简单配置,而后 have fun 。

//命令行安装
npm install --save-dev babel-plugin-transform-runtime

//而后在.babelrc文件中加入
{
"presets": [
"es2015",
"stage-0"
],
"plugins": [ [
"transform-runtime",
{
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": "babel-runtime"
}
]]
}
复制代码
二、多页面

 Weex默认是单页面效果,也就是Android中一个Activity的概念,而单页面效果在原生上,跳转一多效果就会web了。既然叫native,怎么可能如此too young,因此这个时候,就须要修改默认的webpack,让其支持naive多页面了ı╮(╯▽╰)╭。

 首先,要知道Weex真正运行的是,经过entry.js做为入口文件文件,经过webpack,将.vue文件打包成index.js进行使用。Look,多页面的重点,就是将独立页面的.vue文件,生成多个js文件。

入口js

 如上图,参考entry.js文件,建立一个SecondPageEntry.js,做为SecondPage.vue的入口,用于webpack生成SecondPage.js页面。

 什么?webpack没据说过怎么办,No problem,你只需简单的修改,只知其一;不知其二彻底能够胜任。以下图,咱们主要须要修改webpack.common.conf.js文件,

webpack.common.conf.js

 能够看出,webpack.common.conf.js中,实际上是区分了webConfig和weexConfig的不一样打包方式。以下图,其中weexEntry就是咱们须要修改的地方,能够看到原本已经有index和entry.js存在了。

 最后咱们须要经过navigator来实现跳转,咱们须要知道,要跳转的js文件在哪里,以下代码演示,如何实现navigotor的native跳转,完整兼容三端跳转请移步demo项目。

//获取当前js文件所在完整路径
 let bundleUrl = this.$getConfig().bundleUrl;
 bundleUrl = String(bundleUrl);
 let nativeBase;
 //android通常位于file://assets目录下
 let isAndroidAssets = bundleUrl.indexOf('file://assets/') >= 0;
 //ios通常位于通常带有file开头,带有WeexDemo.app
 let isiOSAssets = bundleUrl.indexOf('file:///') >= 0 && bundleUrl.indexOf('WeexDemo.app') > 0;
 if (isAndroidAssets) {
     nativeBase = 'file://assets/dist/';
 } else if (isiOSAssets) {
     nativeBase = bundleUrl.substring(0, bundleUrl.lastIndexOf('/') + 1);
 } else {
    let host = 'localhost:8080';
    let matches = /\/\/([^\/]+?)\//.exec(bundleUrl);
    if (matches && matches.length >= 2) {
        host = matches[1];
    }
    nativeBase = 'http://' + host + '/index.html?page=./dist/';
 }
 return nativeBase;

复制代码
三、样式sass\scss

sass,后期必不可少的利器。

 当你的weex项目不断变大,一些样式共享,公共颜色,大小尺寸等的管理,就是你须要面对的问题。

 这时候sass和scss就能够起到很大的做用。最大优势是,它可编程,支持定义变量,并且不像阉割后的css同样,var()这种写法没法在native下获得支持,这时候sass的效果绝对让你耐人寻味。

 使用sass也十分简单,简单配置下webpack,sass的语法也十分容易上手,只需十分钟了解下就能够愉快的享用这块糖了。

  • 先安装sass依赖:
npm install node-sass;
npm install sass-loader; //依赖node-sass
复制代码
  • 以后webpack.common.conf.js中配置loader,以下图,在两个module处,增长红框配置。

  • 最后用 import 引入的sass文件进行加载,详细可查看demo工程。
//也能够 lang="scss"
<style lang="sass">
//导入写好的文件
@import "./style.scss";
</style>
复制代码

5、蹲坑

 其实就是问题集锦,记录一些开发过程当中遇到的问题,相信你会喜欢:

  • 一、关于vue的<scrpit>标签内,weex.requireModule(包括插件weex-ui)中,在全局获取返回null的缘由,是由于entry.js中的router对象,不能用import 和 export default,只能用require 和 module.exports 配合。

  • 二、es6一些语法问题,如async和await,能够用"babel-plugin-transform-runtime",在.babelrc中设置。

{
"presets": [
"es2015",
"stage-0"
],
"plugins": [ [
"transform-runtime",
{
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": "babel-runtime"
}
]]
}
复制代码
  • 三、export default 和require混合使用的时候,会多一个default对象,好比this.$store.default.state这样才对的问题。

  • 四、自定义的js文件类中,不能使用全局的weex.requireModule

  • 五、使用weex-ui的tabbar结合是,<list>必须有高度,或者overflow属性为scroll才能滑动,并且overflow的位置必须是不会影响其余页面位置。

  • 六、全屏默认height 1334 和 width 750,可是记得减去32大概高度的statusbar。

  • 七、list的loadmore,必须给list设置高度样式,才能在web中正常触发。

  • 八、text的</text>结束标签换行,在debug下可能会出现样式问题。

  • 九、生命周期在web中与android等不一样,好比activated等。

  • 十、()=> {}对于this可能获取存在的不一样,尽可能用function(){}。

  • 十一、多页即建立多个相似entry.js的入口文件,在webpack下配置weex的打开生成的js文件,用于navigator跳转,经过url传值。

  • 十二、android多页面打开失败

android.os.FileUriExposedException问题:

在你的Application中添加:
if (Build.VERSION.SDK_INT>=18) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();
}
复制代码

ActivityNotFoundException问题:

<activity
         android:name=".xxxxxx"
         android:label="@string/app_name"
         android:screenOrientation="portrait"
         android:theme="@style/AppTheme.NoActionBar">
     <intent-filter>
         <action android:name="com.taobao.android.intent.action.WEEX"/>

         <category android:name="android.intent.category.DEFAULT"/>
         <category android:name="com.taobao.android.intent.category.WEEX"/>
         <action android:name="android.intent.action.VIEW"/>

         <data android:scheme="http"/>
         <data android:scheme="https"/>
         <data android:scheme="file"/>
         <data android:scheme="wxpage" />
     </intent-filter>
 </activity>
复制代码
  • 1三、多页面生成js时,import的时候,须要指定.vue后缀的。

  • 1四、若是是webstorm,记得对.temp dist node_modules platforms几个文件夹,右键设置excluded,避免一直indexing和硬盘资源消耗。

  • 1五、@viewappear="onappear" @viewdisappear ="ondisappear" 相似onPause和onResume

  • 1六、ios实时看log,能够先增长

-(void)redirectConsoleLog{
#ifdef DEBUG
    NSString *documentDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    NSLog(@"documentPath : %@",documentDir);

    //重定向NSLog
    NSString* logPath = [documentDir stringByAppendingPathComponent:@"console.log"];
    freopen([logPath fileSystemRepresentation], "a+", stderr);
#endif
}
复制代码
//调用
[self redirectConsoleLog];
复制代码

而后在Devices下,找到对应的模拟器号码,在再Application下,搜索console.log,跟踪执行

tail -f
/Users/your name/Library/Developer/CoreSimulator/Devices/FDEACA11-D84E-4E8F-A6B8-26239559A928/data/Containers/Data/Application/9394D6CC-6B4A-4200-A13D-0CBE6F2BB67A/Documents/console.log
复制代码

最后

一、文章配套,超完整 Weex 项目了解下:github.com/CarGuo/GSYG…

二、react native相关文章

从Android到React Native开发(1、入门)

从Android到React Native开发(2、通讯与模块实现)

从Android到React Native开发(3、自定义原生控件支持)

从Android到React Native开发(4、打包流程和发布为Maven库)

还记得我吗
相关文章
相关标签/搜索