3

最近再次更新了weex-toolkit,版本1.3.8,weexpack版本1.1.6。版本号有了小升级,没发现什么变化,文档更是感觉很久都没变化了。记录下自己发现的一些坑,只是处于探索研究阶段,很多实际开发的功能还没涉及,但仅这些皮毛已经有足够的理由放弃了。

Weex宣称是一次开发、多端适配,这点上比ReactNative需要针对不同端使用不同组件开发的方式看起来美好了很多,无论是成本还是效率,肯定都有巨大的益处。一旦你相信了,兴冲冲跑进去,才发现底下是一个多大的陷阱(如果能爬上来,肯定有很大进步?)。开发时,上层组件看起来是统一了,但下面其实是N多的多端适配补丁,只是将ReactNative多端开发的不同下移了,而且这个不同还是各端Native代码。

Weex总体思想是好的,帮开发者封装不同端的差异,只是感觉这个活刚干了表面一层,剩下就烂尾了。。。

页面跳转问题

页面跳转几乎就是web开发的核心,多页还是单页,对用户是体验感官问题,对开发者则是数据流程等基础架构问题。关于页面跳转weex文档并没有提及,严格说也是提及了,前提是读者有native开发经验。

单页内跳转

单页基于vue-router实现跳转,这种方式还是传统的web开发,能减少很多额外的问题。如果不在乎依赖包的版本比较老旧,那么基于weex-hacknews这个demo修改最简单,相对问题也少。

单页最大的问题,在于你的app就真的成了一个浏览器容器,每次打开都是一个全新的浏览器。

如果想基于weex-toolkit创建的项目做单页开发,需要自己调整很多东西,这个脚手架本身是为了多页而存在的。一些不成体系的趟坑经验见weex vue router开发尝试

多页跳转

这种方式不止是weex-toolkit脚手架应用,也是weex-ui所推荐的,但内层的机制却需要开发者熟悉native的跳转方式,关键这也是开发时必须熟知的。

针对三端(web端是为了方便开发),跳转方式和路径都是不同的:

  • Web端,比较简单,使用document.location,跳转路径使用 /about.html 形式。
  • Android端,跳转要基于Activity(Android开发的基础概念,后续相关的不再备注),有两种方式,一是使用navigator模块,它使用action+category方式跳转Activity,因该模块中写死了category,不改变SDK的基础上,为了防止多个weex应用在被同样的category呼起时冲突,需使用第二种方式,即使用 event 模块,它会显式调用WXPageActivity(脚手架中的java类),重新渲染当前Activity。跳转路径是本地资源路径 file://assets/dist/xxxx.js
  • iOs端,可以正常使用navigator模块(具体的跳转机制与Android不同,这块我不太熟)。跳转路径是本地路径 file://..../bundlejs/xxxx.js 或 hot reload的http://.../xxxx.js
weex提供的navigator模块与event模块都是响应跳转路径的,但是event应该是比较老的方式,因为放到了脚手架源码中,反而可以作为自己开发的自定义模块方便控制。但在Android的跳转机制上,是刷新Activity,而不是跳转新的

脚手架native部分的源码中,很大一部分是处理HotReload部分的,会导致与实际打包后引用业务js路径不同

统一封装一个跳转方法,实现区分代码如下:

/**
 * 跳转页面
 *   根据传入的跳转相对路径(/about、/views/user等),对三端区别处理,添加前后缀
 *   该方法可以通过Vue.mixin()机制全局注入,但src/entry.js中Vue.mixin()无法打包入weexjs,因此需要定义在src/lib/utils.js中
 * @param String url 要跳转的地址
 */
export function jump (url) {
  let platform = weex.config.env.platform.toLowerCase();
  if (url.indexOf('/') === 0) {
    if (platform === 'web') {
      url += '.html'
    } else {
      url = weex.config.bundleUrl.replace(/\/(views\/.+|[^\/]+)\.js$/, url + '.js')
    }
  }
  if (platform === 'android') {
    // android中navigator会根据action+category区分,
    // 为了防止多个weex应用呼起导致冲突,使用event模块方式跳转(显式调用intent)
    const event = weex.requireModule('event')
    event.openURL(url)
  } else {
    const navigator = weex.requireModule('navigator')
    navigator.push({url: url, animated: "true"})
  }
}

有一个需要注意的地方,就是脚手架中Android实现代码有bug,需要修复 WXPageActivity.java中 mUri 赋值问题,否则无论如何跳转,最终都是获取的初始加载页面:

try {
  // 注意这里添加了if块:如果uri不是hot reload传过来的对象,需要为mUri赋值
  if (uri.toString().indexOf('{') != 0) {
    mUri = uri;
  }
  JSONObject initData = new JSONObject(uri.toString());
  ...

flex布局问题

weex默认都是使用flex布局,但是这个布局使用,有一定的限制(仅描述我发现的,可能现象总结不准确)。

如果某个元素定义了 align-items:center,其下任意层级中再有flex布局的组件,不指定高度时,Android无法自动扩充(仅紧挨展现内容),iOs看不到渲染的内容。如果整个页面都保持没有这个特别的样式定义,那么Android是可以正常实现flex布局的自动扩充的。

宽高指定才好安排内容。weex宽度上按750px缩放,可能有细微像素差别,问题不大。可视高度随机型不同、虚拟按键和虚拟键盘收缩而不断变更,如果能自动扩展填充,相对会好很多。可能有些问题是native本身就带有的,比如虚拟键盘弹出,Android原生也是要做特别处理的。

weex-ui中很多组件,尤其是容器组件(一般是带有align-items样式定义的)是要求必须指定高度的,其中的wxc-minibar一类的组件还会减去顶部大概64px的大小,用来计算可视高度,但在虚拟按键存在的机型上,明显被遮挡部分内容。虽然有其他方法一直保持动态计算,但这种方案要求对每个容器都进行高度计算,对后期发展会造成很大的干扰。

欢迎尝试保证整个应用都不设定具体的高度,有可能会带来好的体验。

样式兼容问题

weex样式是无法简写的,虽然写起来比较麻烦,倒也没什么可吐槽的地方。只是iOs不支持层级样式,这点就比较奇葩了。

其他一些样式无效的都算小问题,就没有特别记录了,总有其他方式替代(margin、padding增加空白相互替换等)。

登录态保持

没有cookie,无法自动记录,需要用到storage存储来替代。

因为是多页面,要注意每个页面都是同一套逻辑来检查(check storage->check api)。习惯了单页面总觉得很浪费资源。

组件扩展

按文档做就好了,相对比较简单。唯一需要注意的是native编写完毕后,注意前端的js部分,也要把新组件注册上。


这小半年中,小程序的文档更新的都嫌太快,weex却是一直这个样子,更新最快的恐怕是weex的趟坑记录吧。


Calefy
17 声望0 粉丝

信念是一种会自动实现的预言。


引用和评论

0 条评论