目录
快应用与微信小程序主要区别
公司这次交给我的项目主要内容就是把已经开发好的微信小程序上的功能移植到快应用上,本来以为这个移植是一个非常简单轻松加愉快的过程,但是由于我本人比较菜(主要原因)并且两者也有一定的区别(次要原因),因此前期花费了不少时间才算上手,因此这里对二者主要区别进行一个总结,一些没有用到的功能我也不是很了解区别,因此这里只列遇到过的。
文件结构
如图,快应用中每个页面只需要一个.ux文件,微信小程序是分为四个文件,其中.js,.wxml,.wxss分别对应< script >, < html >和< css >,.json文件则是一些页面配置信息比如上面navigationbar(快应用里面叫titlebar)的标题文字,样式,颜色。在快应用中前三个文件全部整合到.ux里,而页面配置则放到manifest.json文件中。
全局(app)
快应用的app调用就我个人经历来说感觉完全是一个坑。小程序中的app对象在app.js中,全局配置则在app.json中,这些具体的内容参照微信小程序官方文档,而在页面中调用只需使用getApp()方法获得这个对象,之后就可以正常的使用app.js中定义的对象和方法。快应用当中看上去也是类似的,app对象在app.ux中定义,全局配置放在manifest.json中,内容也都和微信小程序差不多(个别功能可能缺少,毕竟出来的比较晚完善度没微信小程序那么高)。但是调用的时候经常各种报错。首先按照快应用官方文档上给出的调用方式:
在页面中使用this.$app.$def.data
调用全局变量一般没什么问题,但是当使用this.$app.$def.function()
调用app中定义的函数时则经常因为异步等操作出现报错:$def undefined
。而当换成this.$app.function()
时问题得以解决。这个错看似简单,但是原因令人费解,耽误了不少时间。
组件和接口
可以说,快应用的组件以及接口相比于微信来说还是比较简陋的。组件相比于微信缺少很多属性,而接口也不如微信全面。印象比较深的一个坑就是storage缓存中的get和set,微信中是支持异步wx.getStorage
,wx.setStorage
和同步wx.getStorageSync
,wx.setStorageSync
两种方式,而快应用中只有异步storage.set
,storage.get
,这个算是很不方便,因此在实现一些同步操作时我采取了如下方式:
storage.get(
key:'key',
success:function(data){
//后续代码
}
)
如上,将同步操作的后续代码放在get成功之后的回调当中,set同理。
组件当中最主要的差别就是微信中基本容器是<view>
,而在快应用中使用的是<div>
。两个基本可以直接替换,除了需要显示文字的部分(快应用中貌似只有<text>
,<a>
,<label>
,<span>
标签可以显示文字)。除此之外快应用中的组件和接口没有微信小程序中那么细的分类,很多微信小程序中的方案可能需要重新设计并替换掉。比如说微信小程序官方的接口wx.showloading
会有一个加载中的动画效果,这个在快应用中就没有类似的接口,可能只能使用prompt.showToast
显示一个加载中的toast提示,相对来说比较简陋。
动画效果和样式
微信当中支持的一些动画效果比如transition之类的在快应用中可能并不支持,不过这个随着后续版本的更新可能会逐渐加入。由于我使用的也不是很多所以这里不多说了,总之一些比较复杂的动画效果很有可能是实现不了的,只能选择替代方案。另外快应用中不支持伪类选择器:after
,并且像z-index这样的图层效果也不支持。
快应用框架中一些需要注意的地方
if和show
首先要提到的一点是快应用的控制块<block>
是不能使用show的,这个要注意。
然后就是非常坑的一点,这个我也是问了快应用官方人员才知道的,if中的条件为false,0,undefined,null和 ''
时都不会显示,而show中的条件只有为0和false
的时候才不显示,也就是说直接将if替换为show或者将show替换为if都是不行的。
然后就是if和show当中的一些条件,比如如下片段:
<block if="{{foo === null}}"></block>
<block elif="{{foo.length===0}}"></block>
<block else></block>
像这个if,elif,else的结构中每个条件语句都会执行,也就是说如果foo是null的话这个就会报错Cannot read property 'length' of null
。这个是快应用里面和js机制不一样,因此需要注意。array.length===0
这种判断条件最好改成array&&array.length===0
这样。
list
快应用中没有微信小程序中的<scroll-view>
组件,取而代之的是这个<list>
,不过相比于<scroll-view>
还是有不少坑的。
首先<list>
不支持<scroll-view>
中的很多功能,比如滚动条,还有一些不太常见的事件,如果有需求只能自己实现。不过这个还不是最坑的,最坑的其实在于<list>
的子组件——<list-item>
。
在快应用当中<list>
的子组件只能是<list-item>
(<block>
也可以,但是<block>
是控制块,最终仍然必须是<list>
的下一层为<list-item>
),而<list-item>
大致与<div>
的功能相同。这个看上去倒没什么,只是要对 <list>
下的子组件外部包一层<list-item>
就行了。但是这个<list-item>
有一个属性——type
。<list>
的出现本就为了解决列表重复太多的性能问题,因此在<list>
中进行复用,而<list-item>
的type如果相同,在复用过程中就会使用相同的结构进行渲染。因此如果要显示不同的内容就必须使用不同的type
。
同时为了保证相同type
的<list-item>
的结构相同,在<list-item>
中尽量不使用if
或者for
。举个例子:
<list>
<list-item type="example">
<block for={{array}}>
<text>{{$item}}</text>
</block>
</list-item>
</list>
这样的写法在实际运行过程中就可能导致渲染出现问题(因为array的长度可能发生改变),正确的写法如下:
<list>
<block for={{array}}>
<list-item type="example">
<text>{{$item}}</text>
</list-item>
</block>
</list>
同理对于if语句,如果在这个item中出现了需要判断的情况,那我建议是分开来写,将if放在item属性里,比如说:
<list>
<list-item type="example">
<text if={{key}}>{{TXT}}</text>
<text else>{{txt}}</text>
</list-item>
</list>
这种就有可能会引起最终渲染出错,建议换成如下写法:
<list>
<list-item if={{key}} type="example-1">
<text>{{TXT}}</text>
</list-item>
<list-item else type="example-2">
<text>{{txt}}</text>
</list-item>
</list>
但是如果这个item本身出现的情况实在太多了,这时候如果将其分离开无疑是不明智的,这种时候就只能将if换成show。但是这样一来就会引起上面提到的if和show判断条件不一致的问题。目前来说,只能在其他地方比如生命周期函数onInit
里面对判断条件进行判断重新赋值(比如判断条件为undefined就手动赋值成false)来解决这个判断条件不一致的问题,非常麻烦。期待官方后续进行优化。
不过顺带一提,在目前的最高版本1050中这个问题(list-item中出现if或者for之后显示有误)并不那么明显,但是在1040中会有报错出现,非常严重。而令人绝望的是虽然快应用是9大厂商联合推出但现在只有小米支持1050,因此如果想顺利进入市场需要至少兼容1030或是1040版本,所以上面提到的问题仍然是不得不解决的。
slider
快应用里的<slider>
和微信小程序里的slider最大的一个不同,就是change
事件。看着名字一样,但是快应用里的change事件等同于微信小程序里的changing
,并不是完成一次拖动后才触发,而是在拖动过程中就会触发。那么快应用中如何实现拖动一次结束后再触发呢?这个目前来说确实没有什么解决方案。一开始我本来准备用通用事件里的touchstart
和touchend
来监听拖动事件的完成,但是最后无奈的发现<slider>
里面根本就不会触发这两个事件,因此最后只能通过增加延时来达到一个近似的效果。代码如下,仅供参考:
if (this.sliderTimer) {
clearTimeout(this.sliderTimer);
}
var time1 = Date.now();
var that = this
console.log('onChapterSlide 我正在阻塞延时器');
this.sliderTimer = setTimeout(function () {
var time2 = Date.now();
var timeout = (time2 - time1) / 1000 + 1;
console.log('onChapterSlide 本应该 ' + SLIDE_TIMER_TIME + ' 秒后执行,结果', timeout, '秒后才执行');
//执行的内容
}, SLIDE_TIMER_TIME);
自定义组件的属性
这个地方主要就是建议自定义组件的属性值用小写,如果使用大写貌似会报错。
华为快应用
华为快应用和其他平台的快应用不同,需要单独进行适配,问题主要集中在样式上。
position
华为里面position:fixed和position:absolute这两个和其他快应用里面显示容易出现不一样,这里需要尝试一下兼容的写法。
class和style
华为快应用里面组件当中的class,有可能因为外部的切换属性操作失效。比如组件中有这样一段:
<text class="{{key?:'class1':'class2'}}"></text>
这个写法一般来说初始渲染的时候不会出问题,但是假如外部改变了key的值来实现样式切换,这个时候会出问题,具体表现为样式效果都没了。。。这个问了官方,也无法确定是什么原因,暂且算作快应用的bug。
解决方案:将样式写在style里。
华为和荣耀
快应用有个接口:device.getInfo(),返回值中的brand代表厂商,如小米返回XiaoMi,但是华为手机有个坑就是荣耀系列的手机不像其他华为手机一样返回HUAWEI,而是返回HONOR,这点也需要注意。
结语
快应用开发过程中还是遇到过不少坑的,所以萌生了写这篇文章的想法。目前总结了一些自己遇到过的一部分坑,还有一些暂时没想起来的如果以后想到再补充到这里,希望能帮助到也刚接触到快应用的同僚。