Weex 详细入坑之旅

一、与 Weex 的缘分

公司接了一个新项目,项目本身也不是很复杂于是我们老大说希望用 Weex 进行跨平台开发,积累跨平台方面的经验,由于我一直是做原生开发的所以刚开始是有点拒绝的,但内心还是很蠢蠢欲动的,所以我重新拾起了往年的前端基础 + 啃了两本 js 书后开始开发,经过几个月的实际开发与体验,我所负责的项目暂时告一段落了,于是趁着机会进行个总结,所以这篇博客就应运而生了, 现在的跨平台框架挺多的而且大前端概念的火热和趋势席卷中国互联网,说实话对于我们移动端的冲击不是一般的大,其实我一直都有关注技术的更新换代和趋势热潮,大前端 和 Web 化对于公司来说无疑是一种快递迭代和节省成本的一种方式,所以兴起算是一种必然吧!同时这也时刻警醒我们这些 IT 从业人员不想过时的话就要时刻有拥抱变化的准备。

二、Weex 介绍

这里我就不多说了直接引用 Weex 官网的介绍:

Weex 致力于使开发者能基于通用跨平台的 Web 开发语言和开发经验,来构建 Android、iOS 和 Web 应用。简单来说,在集成了 WeexSDK 之后,你可以使用 JavaScript 语言和前端开发经验来开发移动应用。Weex 渲染引擎与 DSL 语法层是分开的,Weex 并不强依赖任何特定的前端框架。目前 Vue.jsRax 这两个前端框架被广泛应用于 Weex 页面开发,同时 Weex 也对这两个前端框架提供了最完善的支持。Weex 的另一个主要目标是跟进流行的 Web 开发技术并将其和原生开发的技术结合,实现开发效率和运行性能的高度统一。在开发阶段,一个 Weex 页面就像开发普通网页一样;在运行时,Weex 页面又充分利用了各种操作系统的原生组件和能力。

看起来是不是很牛逼 ?如果你信了~ 啧啧啧 骚年你还是 too young 啊 ~

三、Weex 大致原理

image.png

上面是 Weex 的架构图,从图中我们也能大致看出 Weex 的大致工作流程

1、 首先 Weex 会将编写的 Weex File 通过 weex-toolkit 的转换器 transformer 转换成 JS Bundle

2、 转换的 JS Bundle 可以部署到服务端,方便 Web、Android、IOS 各终端请求相应页面从而实现 hot reload, 当然不部署到服务端是否可以呢? 答案是可以的,如果不部署到服务端在你 run android 的时候回自动把 JS Bundle 放到 assets 目录中,只是这样就失去了 hot reload 作用

3、 当请求到服务端的页面后,各个终端通过 Weex 的 JS Framework 接收和执行 JS Bundle 代码,并且完成数据绑定、模板编译等操作,然后输出 JSON 格式的 VIrtual DOM, DOM 生成后接下来就是将 DOM 渲染成本地原生控件,并且通过 JS-Native Bridge 实现 JS Framework 和 Native 的通信

四、 Weex 环境搭建

1、 官方搭建教程

  • 环境这个没啥好说的,按照官网配置就完事了,但是有几个点还是要注意一下的,由于众所周知的原因如果你无法科学上网的话那么还是有必要做一下 taobao 镜像的,就算你能科学上网我也建议配置,因为我被那糟糕的网速折腾的没脾气,就算 npm install 成功了还老是报莫名其妙的错误,命令如下:

npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install -g weex-toolkit

  • 前端开发环境支持
    我用的是 Jetbrains 的 WebStorm 进行的开发,当然如果你不喜欢WebStorm 也可以换 VSCode 或者其他轻量级编辑器

  • Android 环境支持
    配置Android开发环境:安装Java相关环境,安装Android Studio及Android SDK。在安装编译Android项目时需要保证Android build-tool的版本为23.0.2以上。

  • IOS环境支持
    配置iOS开发环境:安装Xcode、cocoaPods及其相关环境。(需要 MacOs)

2、 一些注意事项

  • Android/IOS 项目必须保证要在 AndroidStudio 或 Xcode 中能够运行起来,否则通过 weex run andorid/ios 的话可能无法 build success !

  • 由于 Weex 是通过 Vue.js 或 Rax.js 进行页面编写,所以如果要想玩 Weex 的话可能需要有一定的 Html+CSS+JavaScript+Vue.js/Rax.js 基础否则无法愉快的玩耍,但是光懂前端也是不行的如果你没有一定的移动端原生基础那么遇到问题你可能会崩溃~

    Vue.js 官网
    Rax.js 官网

  • Weex 支持 hot reload 在运行时会自动监控你的页面变动达到实时刷新的效果,这点真的非常 nice

  • weex 支持 Vue.js 进行页面开发看到这里是不是很开心? 那我只能说那只是你以为,从架构图中可以看到通过 Vue.js 编写的组件在 Android 和 IOS 端上最终都是要渲染成原生控件的,所以这就导致 Weex 不可能支持 Vue.js 的全部特性根据不同平台可能有些特性支持有些不支持,比如 Weex 的尺寸只支持 px 不支持 rem ,对于这些问题官网文挡中的样式、事件一栏已经进行了详细的说明,如果你想玩的话那么务必把这些看完

3、 开始玩耍
如果上述步骤全部完成没有问题的话那么恭喜你,你可以用 Weex 愉快的玩耍了

  • 浏览器成功页面
    创建项目 weex create your-project-name
    启动 npm start
    image.png

  • 移动端 成功页面
    添加 Android / ios 项目 weex platform add android / ios
    运行 Android / ios 项目 weex run android / ios
    image.png

  • Weex 命令行官网介绍
    其实 weex 的一些常用命令都在 package.json 中配置了如下图所示
    image.png

五、Weex 的教程和一些常用库以及 Github 上的一些参考项目

  • WeexPlus
    这是一个 Weex 和 Android 进行 native 通信调用的一个框架由于我的项目有这方面要求所以我将其源码进行了集成自己做了一些改动用起来还是不错的(主要是我也没找到第二个),遗憾的是不支持 IOS!

六、Weex 的一些神坑

6.0、吐槽

Weex 虽然号称 write onec run everywhere, 但在实际开发中并没有那么顺利,一些坑点官网也没有明确说明,而且 Weex 的社区是真的烂,如果需求官方提供的不能满足那么就得自己手撸了,轮子极其稀少,插件市场早就打不开了而且根本就没几个插件,Google Baidu 上面资料少的可怜遇到问题无法解决那么只能看源码自己摸索了,对于新手不是很友好,官方文档的例子我都懒得说了,能在简单点吗? 关于扩展 module 方面光打印一行文字有什么用?而且整个项目已经托管到 Apche 基金会了。。。 拜托阿里你也是国际公司了,以后开源能走点心吗??还有,说是跨平台(Android、IOS、移动 Web 端) 但实际开发其实相差甚远至少移动 Web 端还是算了, 就拿 weex-ui 的组件库来说,部分组件在 Web 端是直接不显示的,而且三端兼顾无论是是开发还是后期维护也是个神坑,所以我明确跟领导说了只兼容 Android 和 IOS 端,而且就这也遇到了不少兼容问题,有的地方 android 可以 IOS 却不行,有的尺寸 Android 显示没问题,IOS 显示就变小了不少诸如此类~~ 所以说跨平台并没有那么美好啊~~

吐槽就到这里吧,毕竟我也改变不了,所以只能发发牢骚写个总结避免后来者踩坑!

下面的坑点主要是结合 GSYGithubAppWeex 项目和自己这几个月开发经验所得,我的项目也大多参考的是这个项目在这里感谢 CarGuo 大神,所以如果你想快速上手 Weex 那么我建议你先把这个项目 run 起来,这个项目中有常用的组件封装,网络封装和一些常用依赖以及 Utils js ,省的你在自己找了。同时这些坑点也可在 CarGuo 大神的博客中找到,而且更详细,下列坑点主要是自己在开发中实际遇到过的问题。

参考博客地址 : Weex原理之带你去蹲坑

6.1 Navigator VS router

页面跳转是一个基本功能对此 Weex 提供了两种方式,一种是通过 router 的方式进行跳转一种是通过 Weex 提供的本地跳转方式 navigator 模块进行跳转,想要知道两者的区别我们还是从使用方式来说

  • Router
    router 是 Vue 提供的一种页面跳转方式通过 router.push router.replace 进行跳转, 在 Weex 中也能使用但体验极差,没有任何过渡动画,跳转极其生硬和 Web 页面跳转一样而且页面跳转后的任务栈结构可能需要自己记录,所以不予采用。

  • Navigator
    作为 weex 内置的跳转模块 Navigator 所使用的跳转是完全的本地跳转方式,这样的话过渡动画直接再本地统一配置即可而且也不用在单独记录页面的任务栈,这也是 Weex 推荐的跳转方式。但 Navigator 使用起来还是稍微有些繁琐的,但并不复杂,只需按如下步骤即可:

第一步

创建一个你要跳转的 Vue 页面例如 JumpDemo.vue

第二步

在 src 目录下创建一个 entry 目录,创建一个同名的 JumpDemo.js 文件里面加入如下代码:

import store from '../store'
import mixins from '../mixins/index'
import * as filters from '../filter/filter'
import JumpDemo from '../components/JumpDemo.Vue

Object.keys(filters).forEach(key => {
    Vue.filter(key, filters[key])
})

Vue.mixin(mixins)

new Vue(Vue.util.extend({el: '#root', store}, JumpDemo))

第三步

在项目根目录 -> configs -> webpack.common.conf.js 中的 const weexEntry 对象中加入如下代码:

const weexEntry = {
    'index': helper.root('entry.js'),
    'JumpDemo': helper.root('entry/JumpDemo.js')
}

第四步 <主要指 Android 端>

这一步很重要,你可以新建一个 Activity 页面例如 WXPageSampleActivity 里面的内容可以直接Copy WxPageActivity 中的代码,然后在 AndroidManifest.xml 中添加如下代码:

 <activity
    android:name=".WXPageSampleActivity"
    android:label="@string/app_name"
    android:screenOrientation="portrait">
    <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>

通过以上四步即可使用 Navigator 进行页面的跳转了,具体如何跳转请查看 weex 官方文档

6.2 全局的页面状态管理

Vuex 非常适合 Vue 在单页面下的全局状态管理,但一旦涉及到多页面就没什么作用了,因为每一个 Navigator 页面都是一个单页应用,所以本项目中后面基本用内置模块 storage 来代替 Vuex 的作用。

6.3 text 组件换行

weex 是比较推荐使用 iconfont 来展示一些应用图标的其中 text 通过简单配置可以用来展示 iconfont 图标,但是 text 组件有个 bug 那就是一旦标签换行那么 iconfont 就不显示了。 (weex sdk 0.16.0 )

6.4 全局 module 问题

自定义 js 文件中不能使用全局的 weexModule

6.5 async 、await 支持

async 、await 支持需要在 .babelrc 文件中配置


{
 "presets": [
   "es2015",
   "stage-0"
 ],
 "plugins": [ [
   "transform-runtime",
   {
     "helpers": false,
     "polyfill": false,
     "regenerator": true,
     "moduleName": "babel-runtime"
   }
 ]]
}

6.6 weex-ui的tabbar

和weex-ui的tabbar结合,list必须有高度,或者overflow为scroll才能滑动,而且overflow的位置必须是不会影响其他页面的

6.7 width and height

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

6.8 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>
 
6.9 Weex 的列表组件

Weex 提供的列表组件我真的是无力吐槽,列表展示没什么问题,但如果展示九宫格那真的是恶心到我了,不像我们 Android 使用 RecyclerView 指定 GridLayoutManager 就可以展示九宫格列表, Weex 只能从数据上下功夫,可能我没找到相应的方法?? 反正我是没找到

  • 展示列表的数据类型很简单就一个数组就行
list : [
  {title:'hello',value:'world'},
  {title:'hello',value:'world'},
  {title:'hello',value:'world'},
]

<list>
    <cell v-for="(item, index) in list">
       <div :style="{width:'750px'}">
            <div class="cell-container row align-center">//样式需要自己定义
                <text class="item-text" >{{item.title}}</text>
                <text class="item-text" >{{item.value}}</text>
            </div>
        </div>
      </cell>
</list>
  • 展示九宫格列表的数据就没那么方便如下所示,一行展示几列那么控制 list 中的元素就行
gridList : [
 { 
   list: [
    {title:'hello',value:'world'},
    {title:'hello',value:'world'},
    {title:'hello',value:'world'},
  ],
 },
 { 
   list: [
    {title:'hello',value:'world'},
    {title:'hello',value:'world'},
    {title:'hello',value:'world'},
  ],
 }
]

<list :style="{width:'750px'}">
 <cell class="rows " v-for="(group, i) in gridList" :key="i">
  <div class="item center" v-for="(data, j) in group.list">
    <div class="item-back center" :style="{width:'220px',height:'220px'}">
      <div class="column" :style="{width:'220px'}">
        <text :style="{fontSize:'26px'}">{{data.title}}</text>
        <text :style="{fontSize:'26px'}">{{data.value}</text>
     </div>
    </div>
   </div>
  </cell>
</list>

可是这种数据格式写着也太费劲了,我给服务端同事看他也是老大不愿意,所以我只好自己设计了一个转换函数如下

/**
 * 由于 weex 的网格列表展示原因,目前没有找到好的解决方案
 * 所以写了此方法将任意数组转换为weex能展示的网格数据格式
 * 例如传入 list = [1,2,3,4,5] 将会转换为如下格式
 *
 * [{[1,2,3]},{[4,5]}]
 *
 * @param list 传入的数组集合
 * @param num 水平方向几条数据
 */
export function convertToGrid(list, num) {
    if (!list) {
        return false;
    }
    let index = 0;
    for (let i = 1; i < list.length + 1; i++) {
        if (i < list.length && i % num === 0) {
            index++;
        } else if (i === list.length) {
            index++;
        }
    }
    console.log('index : '+index);
    let x = 0;
    let tempList = [];
    for (let i = 0; i < index; i++) {
        let obj = {};
        let data = [];
        for (let j = 0; j < num; j++) {
            data.push(list[x]);
            x++;
            if (x === list.length) {
                break;
            }
        }
        obj = {data};
        tempList.push(obj);
    }
    return tempList;
}

七、总结

Weex 这款框架总体还是很不错的,毕竟没有 RN 那么重很轻量级的一个框架,不过论社区维护和资料文献 Weex 可以说基本没有,轮子太少,这就让开发的效率会变得很低,而且如果要调用移动端的原生功能还是需要 Android / IOS 开发人员的支持的成本也没减多少,而且从我实际的体验来说 Weex 真心不适合全应用开发,只适合嵌入到原生页面中使用,比如某个页面可能因为业务频繁的变动那么这个时候就可以考虑嵌入 Weex 页面实现 hot reload 避免频繁发版,但如此我还是不建议使用 Weex 这个框架,开发过程实在让我一言难尽,如果能重来,我选择拥抱 Flutter ~~ 阿里这个 KPI 项目还是有哪凉快哪待着去吧~~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值