weex项目弃坑小结

由于weex 的不稳定性,所以中途放弃了 weex 方案。转而使用 Android原生开发。今天项目第一阶段开发结束,来总结一下 weex 的一些东西。

weex 相比于原生开发的好处

  • 界面搭建速度快,特别是重复性界面。
  • 数据处理方便,尤其是json解析方面。

坏处么

  • 用的人太少,所以网上资料也很少。
  • 坑还是比较多的,要玩的溜要踩上不少坑。
  • 还是需要一些原生开发的知识才能够玩的溜。

说说我这个项目的一些东西吧~

页面跳转

第一个困扰我的就是页面跳转,我去SF上提问了Weex的页面跳转方案的选择这个问题。

  • vue-router 方案由于 Vueweex 的差异性,用法有所不同,好像需要使用注入 minixs 机制,挺麻烦的,所以放弃了……这个如果有需要我会再去研究一下的。
  • 第二种方案就是每个页面都是单独的 Activity,各自嵌入一个 weex 页面。但是有个问题:weex 如何与当前 Activity 交互,比如我要从页面A跳转到页面B,我需要 weex 调用 ActivitystartActivity 方法,这个交互方式我没有找到。不然倒是可以随心所欲的在原生开发和weex之间来回交互。暂时来说我只知道通过globalEvent和Module扩展来实现两者的交互
  • 最后,还是选择了官方推荐的 Navigator 来作为页面跳转的方式。这种方式能够很快速的实现页面跳转。不用瞎折腾~

选定方案之后,就要解决几个问题了。多页面打包和跳转所需的 Activity

多页面打包

navigator 的跳转方式,需要获取打包好的 weex 的文件路径来进行页面跳转和显示,所以我们就需要多页 weex 文件代表每一个页面。

navigator.push({
  url: 'http://dotwe.org/raw/dist/519962541fcf6acd911986357ad9c2ed.js',
  animated: "true"
}, event => {
  modal.toast({ message: 'callback: ' + event })
})

需要配置 Webpack 来实现这一目的。我将每个页面的入口文件都放在 ./src/entrys文件夹下,通过 nodefs文件模块 读取里面的入口文件,并将他们传给 entry 入口对象。最后将入口对象配置到 webpack 打包配置中。

var path = require('path')
var webpack = require('webpack')
var fs = require('fs')

var files = fs.readdirSync('./src/entrys')
var entry = {}
files.forEach(function (file) {
  var item = file.replace('.js', '')
  entry[item] = path.resolve('./src/entrys/' + file)
})

var bannerPlugin = new webpack.BannerPlugin(
  '// { "framework": "Vue" }\n', { raw: true }
)

function getBaseConfig() {
  return {
    entry: entry,
    output: {
      path: 'dist'
    },
    resolve: {
      alias: {
        '@': path.resolve('./src'),
        'views': path.resolve('./src/views'),
        'utils': path.resolve('./src/utils')
      }
    },
    module: {
      // ESLint配置
      preLoaders: [{
        test: /\.vue$/,
        loader: 'eslint',
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        loader: 'eslint',
        exclude: /node_modules/
      }
      ],
      // 如果注释掉以上这段将不产生ESLint检查
      loaders: [{
        test: /\.js$/,
        loader: 'babel',
        exclude: /node_modules/
      }, {
        test: /\.vue(\?[^?]+)?$/,
        loaders: []
      }]
    },
    vue: {
    },
    plugins: [bannerPlugin]
  }
}

var webConfig = getBaseConfig()
webConfig.output.filename = '[name].web.js'
webConfig.module.loaders[1].loaders.push('vue')

var weexConfig = getBaseConfig()
weexConfig.output.filename = '[name].weex.js'
weexConfig.module.loaders[1].loaders.push('weex')

module.exports = [webConfig, weexConfig]

每一个入口文件都会产生两个相应名称的文件,如 sign.js 的入口文件就会生成 sign.weex.jssign.web.js 文件,这里我们只关注 weex 后缀的文件,这就是我们跳转页面所需的文件。具体项目结构请看源代码
更多对于 webpack 的了解可以看Vue.js学习系列四——Webpack学习实践

navigator跳转的Activity哪里来的?

在使用了 navigator 后一开始发现并没有页面跳转效果,而是报 ActivityNotFoundException 的错误。后来装了 weex 的 playground 之后发现可以跳转了,但是跳转过去的 Activity 有个 ActionBar 和一个性能调试的悬浮窗,是 playground 里面扫二维码显示的结果的那个 Activity。几经查阅后发现原来跳转的 Activity 是一个有着特殊 intent-filterActivity
关于这个问题我写过一篇文章:WEEX 使用navigator跳转Android系统出现ActivityNotFoundException报错
解决方案是我把 Playground 里面的那个 Activity 移到了我的项目中来,并且去除了 ActionBar 和调试工具。然后卸载掉 weex 的 Playground,这样就能愉快的显示 navigator 跳转的 Activity 了。代码请看WXPageActivity。

网络通信

网络通信上我用的是stream,这个很简单。说下两点:
第一,stream所用的url需要是UTF-8格式的,如果URL中有中文需要转一下,URL可以参照utf8这个文件。
第二,提交数据的时候需要添加头文件。我的项目中是这样~

      stream.fetch({
        method: StreamType,
        type: 'json',
        headers: {
          'Content-Type': 'application/json'
        },
        url: url,
        body: JSON.stringify(this.DataObj)
      }, res => {
        console.log(res)
        let json = eval('(' + res.data + ')')
        modal.alert({
          message: json.Message
        }, event => {

        })
      })

图片加载

图片加载需要在ImageAdapter中稍作处理,我这里用的是 Picasso 来显示图片的~

public class ImageAdapter implements IWXImgLoaderAdapter {
    
    @Override
    public void setImage(final String url, final ImageView view, WXImageQuality quality, WXImageStrategy strategy) {
        WXSDKManager.getInstance().postOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (view == null || view.getLayoutParams() == null) {
                    return;
                }
                if (TextUtils.isEmpty(url)) {
                    view.setImageBitmap(null);
                    return;
                }
                String temp = url;
                if (url.startsWith("//")) {
                    temp = "http:" + url;
                }
                if (view.getLayoutParams().width <= 0 || view.getLayoutParams().height <= 0) {
                    return;
                }
                Picasso.with(WXEnvironment.getApplication())
                        .load(temp)
                        .into(view);
            }
        }, 0);
    }
}

页面跳转的数据传输

这一点上,我只想到了不太优雅的方式——使用 storage 来保存和读取。比如我需要将表单ID传递到下一个页面我是这么做的:

    toDetail(AssessID) {
      storage.setItem('AssessID', AssessID)
      navigator.push({
        url: ViewServer + 'GAD.weex.js',
        animated: 'true'
      }, event => {
        console.log('successful entry')
      })
    },

到第二个页面去获取数据:

    getData() {
      let that = this
      storage.getItem('AssessID', event => {
        let AssessID = event.data
        console.log('AssessID = ' + AssessID)
      })
    },

如果是比较多的数据,我会将数据以 json 字符串的形式保存,在需要的时候获取字符串并解析为 json 对象。

如何在返回上一页面时做一些操作?

我的解决方法是在Activity的onResume方法中发送一个消息,然后在weex端添加监听事件。
Android端

    @Override
    protected void onResume() {
        super.onResume();
        if (mInstance != null) {
            mInstance.onActivityResume();

            new Handler().postDelayed(new Runnable() {
                public void run() {
                    Map params = new HashMap<>();
                    mInstance.fireGlobalEventCallback("onResume", params);
                }
            }, 500);
        }
    }

weex端

    addListener() {
      globalEvent.addEventListener('onResume', e => {
        storage.getItem('PopCallback', event => {
          if (event.data === 'update level list') {
            this.loadData()
            storage.setItem('PopCallback', '')
          }
        })
      })
    }

由于加载 weex 有一些延时,onResume 往往会比 weex 加载快,所以我在 onResume 中添加了0.5秒延时。之后在 weex 中添加监听器监听 onResume 的生命周期,并监听返回的数据。

如何控制weex的Slider显示第几页

想实现Android的ViewPager效果,使用了weex提供的slider组件,具体坚决方案看如何控制weex的Slider显示第几页。

其他

  • 图片的存放好像只能是网络图片的URL,所以我将所有图片都放到服务器上让weex去访问。
  • CSS使用flex布局来做,官网上有例子。也可参照Flex 布局教程:语法篇。

最后

啰嗦一大堆,希望某些东西能够对他人有所帮助吧~
项目地址在此,由于是公司项目,所以把服务器地址去掉了,后端数据获取不了。不过代码都是在的,可以进行参考。希望能对大家有所帮助~
最终不用weex的原因么,因为这玩意看似简单,但是想实现点复杂的、和原生交互的功能都得折腾好一会儿。关键还是资料太少,不靠谱,万一哪个地方报个奇怪的错误找不出问题、查不到资料、看不懂源码,那不就挂了嘛所以,爱折腾玩玩可以,放项目中还是有待考虑。毕竟还是要求稳

你可能感兴趣的:(weex项目弃坑小结)