前言
其实我们常用APP的人,对于一个页面是原生APP还是hybird APP,我们往往一眼就能看出来谁是网页质感、手感,谁是原生质感、手感,但是真让你说两者差别在哪里,你可能又一时说不出。今天我就试着讨论一下这个问题。
下文主要对比讨论网页和原生的区别,而且,下文中我所谓的网页,是假定没有优化的、做的非常弱鸡的、前后端分离且JS渲染的网页,显然,uni-app很容易做出这种网页。而我所谓的原生,是假定优化的很棒的原生。只有这样,我们才能最大限度地优化网页,让网页尽量贴近原生体验。
图片
原生APP的图片有什么特点?
懒加载,没有加载成功的时候,有占位图案,或者即便没有占位图案,至少宽高是撑起来的,而网页会从一个小点突然变成一张图,容器由扁的突然撑高,尤其是使用了Vue等框架的前提下。
原生的图片尺寸都是严格规定的,会为不同dpi准备生成@2、@3的图片,而网页可能由一张非常大的图片用样式缩小,然后直接用,于是很卡顿。
解决方案
- 一定要给所有图片设定写死的宽高。
因为uniapp为了兼容小程序,它的<image>组件是有默认宽高的,这跟HTML的<img>是2个概念,所以,最好给每一张图片都设定写死的宽高(所谓写死当然不是指用px单位,应当用rpx单位)。
- 关于图片实际大小的问题。
现在主流手机的ppi都是3,也就是说,主流手机的CSS像素宽度是360像素,设备像素宽度是1080像素,因此,一张全宽的图片,设计它的时候,它的宽度像素应当设为1080像素即可,就是说,uniapp里面750rpx宽度的图片,设计的时候按1080像素做,比例是1.44倍,代码里写图片宽度的时候不要写1080px,而是写750rpx。
可能美工大人会说,不是按照750px宽度设计吗?
这特么老黄历了,五年前的规矩也该变变了。
- 首屏使用占位图,也就是骨架屏。
骨架屏的本质就是灰色的背景色,只在首屏使用即可,也没必要使用第三方组件库,自己调一调就出来了。
- 预加载后一页的首屏数据和图片。
除了骨架屏,我们还有一种更新的技术是,前一页闲时加载后一页首屏的数据和图片。当图片有了缓存,当然就秒开了。
当然,有个前提是,从统计后台看,你的用户有大概率会进入该下级页面,达到一定概率值,才值得为该下级页面做预加载,不可能给所有下级页面都使用预加载。
- 首屏用菊花图。
一个页面有N个下级页面,不可能全都提前加载数据和图片,这时候,对于不重要的页面用用菊花图也无妨。也就是说,开场菊花图转啊转,然后ajax首屏数据,然后js渲染,然后监听图片load事件,等一切全搞定,才给全页面执行show,并开始加载下方的数据和图片。
所以下方的内容并不是一进页面就ajax,而是需要监听全页面是不是show了,只当show了才开始ajax下方的内容。
- 首屏下方图片使用懒加载。
首屏下方的图片不可能用菊花图,用懒加载即可。那么骨架屏和懒加载的区别是什么?骨架屏是连图带文字全都要做骨架,懒加载只是图片做即可,效果类似,都是灰色的底色。关于懒加载方案,uniapp的<image>的lazy-load属性支持APP(不支持H5),所以APP可以用。
- 使用交错GIF、交错PNG、渐进JPEG。
交错GIF、交错PNG、渐进JPEG是一种更先进的图片,它们的意思是,图片显示不是从上到下一点点展开,而是尽快充满全部面积,然后慢慢由不清晰渐变到清晰。作图工具都能制作这种图片,就看你觉得值不值得费这个力气了。
- 解决uniapp做的APP会闪烁的问题。
当页面结构复杂,css样式太多的情况,使用<image>可能导致样式生效较慢,出现 “闪一下” 的情况,此时全局设置image{will-change: transform}
可优化此问题。
到此,对于图片的处理就非常接近原生了。
容器
原生APP的容器有什么特点?
跟图片一样,APP的容器也是默认撑起高度的,而弱鸡网页的容器可能在打开的瞬间是无高度的,因为没内容,等ajax到内容后才忽然撑起高度。
APP的列表是惰性渲染的,只有接近展现的时候才会渲染,滚动也相当丝滑,而弱鸡网页没有这种优化。
真1像素发丝线。
原生通常是首页、无限加载的列表没有滚动条,正文有滚动条,而弱鸡网页一律有滚动条,或者是懂得用
::-webkit-scrollbar
隐藏滚动条,然而,在APP端并不生效。
解决方案
很多方案跟上面相似。
- 首页首屏可以采用骨架屏。
骨架屏可以做到提前撑起容器高度。
- 首页首屏也可以采用菊花图。
也可以放弃撑起高度这个念头,直接先白屏+菊花图,然后一瞬间呈现全渲染好的容器。
首页下方骨架屏和菊花图都可以,根据场景定。
列表建议使用.nvue。
对于无限滚动的列表,或者数量超过50个的列表,就建议用.nvue,且使用list组件(https://uniapp.dcloud.io/component/list)甚至使用recycle-list组件(https://uniapp.dcloud.io/component/recycle-list)。
- 对于参差瀑布流建议使用.nvue。
应使用waterfall组件(https://uniapp.dcloud.io/component/waterfall)。
- 真1像素发丝线。
当然要实现,这是起码的。方案就不说了,可以上网搜索。
- 隐藏滚动条。
微信小程序给出的解决方案是使用<scroll-view>、开启enhanced
,关闭show-scrollbar
,但是在APP上无效。APP上应该是使用.nvue + <scroll-view>,即:
<scroll-view :show-scrollbar="false" scroll-y>
由此也可知,.nvue是必须学的,而且在各种首页上必须使用。
手势
原生APP的手势有什么特点?
什么是手势?就是手指拉出浮层、拉走浮层等等。比如新闻APP,文章下面有评论框,默认是一行高度,点击它,会浮出浮层,往下一划,就收起浮层。
除此之外,还有触底刷新、下拉刷新等等。
H5网页开发一般不会考虑手势,怎么接近这种原生体验呢?
解决方案
- 拉出、拉走浮层。
uni-app并没有更高级的手势封装,只能使用原始的@touchstart、@touchmove、@touchend,好在玩法并不难,随便举个例子:
<view class="somearea" @touchstart="start" @touchend="end">
</view>
let startData = { clientX: null, clientY: null }
export default {
methods: {
start(e) {
startData.clientX = e.changedTouches[0].clientX;
startData.clientY = e.changedTouches[0].clientY;
},
end(e) {
const subX = e.changedTouches[0].clientX - startData.clientX;
const subY = e.changedTouches[0].clientY - startData.clientY;
if (subY > 50 || subY < -50) {
console.log("上下滑");
} else {
if (subX > 100) {
console.log("右滑");
} else if (subX < -100) {
console.log("左滑");
} else {
console.log("无效");
}
}
},
},
};
接着就是添加动效。
- 触底刷新、下拉刷新。
uni-app自带,能用一定要用,如果追求与众不同的触底刷新和下拉刷新,一定要使用nvue的refresh组件(https://uniapp.dcloud.io/component/refresh)。
动效
原生APP的动效有什么特点?
原生的动效特点是——至少原生还有点动效,能给人一种高级感,而网页就是那么干巴巴的,屁动效都木有。
解决方案
解决方案就是拒绝干巴巴咯。这就需要创意了,比如淘宝网,随便点开一张商品缩略图,你看到的不仅仅是图片放大,还有变大的动效,另外图片周围会有一些文字有入场效果。当增加了新功能,或者打算主推一个功能的时候,如果怕用户无法发现新功能的入口,就可以给按钮加个流光溢彩效果。等等等等。
这个话题就不展开说了,特效该抄袭就抄袭,没啥不好意思。
组件
原生APP的组件有什么特点?
原生APP的组件肯定有自己独特的外观和操作体验,而uni-app的组件跟微信小程序一个样,让人有一种感觉就是好似在用微信小程序,这肯定是不行的,就比如Toast,微信小程序的成功Toast是一个对勾,而你的APP的对勾跟小程序一模一样,会让人以为你这个APP跟腾讯有一腿。
解决方案
要么自己写组件,那么使用第三方组件库。
总结
经过这样一番折腾,不信你的APP不像原生!