1.HyBridApp界面开发
移动端界面适配方案
设计稿的还原方案
1.页面适配
移动端页面适配是前端开发领域的老问题了。随着系统和设备的更新迭代,目前只要在页面头部设置 viewport 适配代码,再配合 flex 弹性布局,基本上适配大部分的页面。
1.viewport
//viewport适配代码
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
2.rem
但上述方式只能实现相对“粗略”的适配,即便设置了 viewport,不同手机间的像素仍然存在差异。市面上常见尺寸中,宽度最小的手机只有 320px,最大的 iPhone 8 Plus 却达到了 414px,这种情况下想用 px 实现精细布局已不太可能。我们需要一种可以随屏幕宽度变化而变化的相对单位,才能做到真正的适配。目前,rem 方案的可靠性和兼容性已经得到业内的广泛认可,这里也推荐一种非常简单的基于 rem 的适配方案。
适配原理是先假定我们的屏幕宽度为 640px,此时将根节点(html)字号设置为 10px,即 “1rem=10px”,进而得到屏幕总宽度等于 64rem。
html{font-size:10px;}
/* 此时屏幕宽度 = 64rem */
当以此标准实现的页面运行在其他设备上时,我们只要通过改变根节点的字号,使“屏幕总宽度=64rem”这个等式始终成立就可以了,之前的做法是使用 JavaScript 检测屏幕宽度,然后计算出 rem 的值。
var html=document.documentElement;
var rootSize = html.clientWidth / 640 * 10;
html.style.fontSize=rootSize+'px'
3.vw
得益于规范的推广和手机系统的更新,如今我们用 CSS 也能实现相同效果,因为新规范中有一个 vw 单位,能够以屏幕宽度为单位1,实现任意百分比例的取值,即:
屏幕宽度=100vw
100vw = 64rem
1rem = 1.5625vw
实际上这样就实现了屏幕总宽度恒等于 64 rem,然后就可以愉快的使用 rem 单位做可以适配任何屏幕的精确布局了。
以上是理论,实际上这里会产生一个 Bug。由于多数屏幕的宽度都小于 640px,计算出来的 rem 也会小于 10px,但 WebKit 内核会强制将最小字号锁定在 12px,这将直接导致我们的适配等式无法成立,从而在应用中出现较大的偏差,所以实际开发中我们要将根节点(html)字号矫正为 15.625vw ,适配等式就变成了“屏幕总宽度=6.4rem”,那么“1rem=100px”,可以绕过 WebKit 的限制,同时开发中的换算压力也不大。
4.最终解决方案
说了这么多,真正需要写的代码只有一行:
html { font-size: 15.625vw;}
<div style="width: 3.2rem;height:3.2rem;background:hotpink;">
在任何手机屏幕上都显示为屏幕宽度50%的正方形
</div>
前端基于这套适配方案开发,需要将设计稿宽度约定为 640px,当在设计稿上量取20px时,代码中只要除以100,就可以很简单的换算得到 0.2rem。
如果设计稿宽度不是 640px(设计稿尺寸往往大于640px),也没有关系,这时可以有两种做法,一是根据实际设计稿尺寸修改根字号的值,但可能出现在算根字号的时候除不尽,勉强四舍五入的话,就会产生适配偏差,不推荐这么做;另一种做法就简单了,直接把设计稿的宽度修改为640px,也是推荐大伙使用的方法。
2.设计稿还原
提升网页的精细程度可以从两方面入手,一是使用技术手段排除显示层面的模糊现象,二是用心还原设计意图。
1. 显示模糊-图片模糊
常见的显示模糊有两种情况,一是图片模糊,二是边框模糊,有经验的前端开发者应该对这两个问题都不陌生。
图片模糊的原因是手机屏幕的可测量尺寸与物理像素尺寸不一致,通常 Web 前端会习惯性的将图片尺寸切成可测量尺寸,而图片显示最清晰的状态应该是图片尺寸与显示屏的物理像素尺寸一致的时候。
以iPhone8的屏幕为例,添加 viewport 适配代码以后,屏幕的可测量宽度为 375px,但这块屏幕的物理像素宽度却是 750px,说明这块屏幕的像素比(DPR)是2,也就是说显示的时候会用2个物理像素去模拟一个像素,来提高屏幕的显示精度。
总而言之,本地图片尽量做大,远程图片根据需求和场景做适当取舍,不能只为了显示清晰而丢了加载速度。
2.显示模糊-边框问题
边框模糊也就是经典的 1px 边框问题,其产生的原因,从本质上来讲,跟图片模糊的原因一样。用 CSS 画出的 1px 只是可测量尺寸上的 1像素,不能保证就是物理层面上的1像素。在视网膜屏成为标配的今天,CSS 画的 1px 边框基本上都会被呈现为物理像素 2px 或 3px,到了界面上就会显得不精细,跟原生显示的真正1像素有明显差异。
1px 问题的解法有很多,其中利用 transform 所实现的方法应该是最方便的解法了,结合为元素和媒体查询。代码如下所示:
.border-bottom{border-bottom:1px solid #ccc;}
@media screen and (-webkit-min-device-pixel-ratio: 2) {
.border-bottom{position:relative;border:0;}
.border-bottom:before{
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 1px;
content: '';
transform: scaleY(.5);
background-color: #ccc;
}
}
这样显示出来的是真正的1像素边框,看上去非常锐利,显得界面更精致。
3.还原设计
还原设计这个点其实没有太多可说的,作为前端开发应该对设计稿进行还原。但在PC 时代还原设计还好说,毕竟直接量设计稿就可以达到像素级别的精度,但在混合应用开发中,压根就不存在什么像素级还原。因为最终的界面要跑在各种不同尺寸的屏幕上,这个界面是没有标准答案的,我们前端能做的只能是在所有屏幕上都尽可能的还原“设计意图”,不至于让界面看上去跟设计稿不是一回事。
这里简单提一下比较容易出问题的两个点。
首先是字号设置。我们使用的 rem 适配方案,理论上只要所有单位都用 rem 实现,是可以将设计稿完美适配到所有屏幕的,但文字是界面上比较特殊的一类元素,它们的适配逻辑并不应该简单的仿效布局适配。对于阅读性文字理应设置成一个最适合阅读的固定尺寸(px),大屏就显示的多一些,小屏就显示的少一些,而不是随着屏幕宽度增加而等比增大字号;修饰性文字则完全可以使用 em 单位做相对缩放,这样从逻辑上更能体现其与父元素之间的关系,而不是强调其与屏幕宽度之间的关系,这一点当手机横屏显示时差异非常大,使用 rem 单位的文字在横屏下会大的离谱,甚至会直接导致布局失效。
所以我们通常还是会用 px 或者 em 单位进行字号设置。但这样做也存在问题,就是只要稍微设置不当,就显得文字与周围布局不协调,从而破坏设计意图。这时候可以反复调整字号大小,并对比观察界面和设计稿,直到它们看上去感觉一样为止。
/*阅读类文本使用固定像素*/
.p{font-size:14px;}
/*标题类文本使用相对字号*/
.pro_title{font-size:1.2em;}
.channel_title{font-size:1.8em;}
除了字号以外,有些间距设置有时也不应该使用 rem 单位,究其根本还是因为它们从内在逻辑上就跟屏幕宽度没关系,比如说文字列表的 padding:
这个间距从设计意图上说,是列表项文字的“呼吸空间”,它的大小应该只跟文字大小有关系,凡是这种地方,都没有办法“像素级”还原设计稿,我们只能用心调试,去忠实的还原设计意图。其中em是相对单位,相对于父元素的字体大小。
/*使用em单位设置文字间距*/
.item{...;padding: 1.2em;}
总结下来,凡是跟布局无关的地方,其实都不太适合用 rem 单位,这些地方都需要我们认真对待,避免失真,只有所有细节都做好了,才能整体呈现出较高的还原度。
总结
在混合应用的界面开发中,在处理好了页面适配之后,尽可能精细的还原设计稿,对于图片和线段的显示模糊知道如何解决,不同于PC网页,移动端设计稿在还原时因为屏幕尺寸不一,无法做到像素级别还原,这时就需要根据设计意图进行还原。
2.HyBridApp优化体验
了解HyBird App中前端优化的内容
了解HyBrid App中原生优化的内容
1.页面加载优化
在Web开发中用到的加载提速,呈现提速这些优化手段在 Hybrid App 开发中多数仍然适用。
Hybrid App 会将页面打包到本地,资源加载问题虽然得到了一定程度上的缓解,但不代表我们就可以完全无视加载问题。实际上以当今手机的平均性能水平来看,如果页面的 CSS 和脚本体积过大,仍然可能造成肉眼可见的渲染延迟,这在 App 中是不能容忍的。
造成渲染延迟的原因,第一是由于静态资源读取慢,第二是手机的运算能力普遍不足,导致页面绘制时间和脚本执行时间过长,所以 Hybrid App 开发中我们仍然要对页面性能严格要求,务必保证页面打开后立即呈现。其中涉及代码压缩合并、CSS 性能、JS 性能等问题属于前端基础知识,这里不再展开。
2.图片加载优化
图片是最能拖慢页面显示速度的元素,在图片扎堆的列表页上这个问题最为严重,如果有必要我们也可以采用 Web 中常用的图片懒加载技术,但懒加载的本质是分散加载时间,提升首屏展示速度,资源总加载时间并没有减少,所以如果首屏显示不是特别迟滞,使用懒加载的意义并不大。给图片提速最好的解决方式是缓存,有条件可以使用 CDN 加速,没条件可以在 App 端做图片缓存,但这需要结合原生能力
3.数据加载优化
App 界面除了页面自身结构外,往往还有很多内容是由异步数据渲染出来的。对于这些业务数据,我们没办法要求“立即呈现”,在等待数据的过程中,我们可以从三个方面着手提升体验,首先是让页面框架先加载,内容区域填充占位内容,给用户造成立即呈现的错觉;其次要显示生动且合理的加载动画,缓解用户的等待焦虑;再次从数据源着手提速,可以考虑加带宽,或者减少单次请求数据量等方式,给接口提速,毕竟这才是一切问题的根源。
第一种优化手段也有一个别名做骨架屏,即实现一个只包含布局骨架的页面,每次先加载,内容区域可以填充一些占位元素,等待异步数据就绪再填充真实内容:
骨架屏的重点是占位元素的实现,大致分两种方式。
一种是手写占位元素,数据回来之后,然后用真实内容的 DOM 元素直接替换
另一种思路是利用真实内容的 DOM 结构和样式占位。
其中第一种代码大概思路如下
<style>
.shell .placeholder-block {
display: block;
height: 5em;
background: #ddd;
margin: 1em;
}
</style>
<div class="shell">
<div class="placeholder-block"></div>
<div class="placeholder-block"></div>
</div>
效果如下图所示:
这种方式比较简单直接,但缺点是占位元素的样式需要单独维护,如果整个项目涉及多处不同的占位元素,工作量就比较大了。
第二种是为真实Dom在占位状态下叠加一个样式用来呈现 loading 状态,我们看下面这段代码:
<style>
.list{overflow:hidden;}
.list .avat{float: left;width:5em;height: 5em;overflow:hidden;border-radius: 2.5em;margin-right: 1em;}
.list .title{height: 5em;overflow:hidden;}
/*占位元素通用类*/
.placeholder .avat { background: #ddd; }
.placeholder .title{ background: #ddd; }
</style>
<div class="list placeholder">
<div class="avat"></div>
<div class="title"></div>
</div>
效果如下图所示:
当真实内容渲染后,需要将占位状态的叠加类去掉,最终效果差别不多,大伙可以根据需求选取使用的方案。