前端应该保证用户体验之承前启后的骨架屏

334 阅读4分钟

大家都知道骨架屏的作用是提升用户体验,那你知道是如何提升的吗?

骨架屏的作用是优雅的占位,所谓优雅,就是贴合的尺寸,适时的退场。

想要做到优雅,就要理解骨架屏的两大核心元素,状态和时机。

状态处理

只有开、关两种状态,初始值为开。

image.png

上图是一个常见的骨架屏应用场景,有若干个步骤组成。

  1. 展示骨架屏
  2. 请求数据
  3. 处理数据
  4. 关闭骨架屏
  5. 展示数据

如果在第二步,或者第三步的时候出现了问题,比如

  1. 接口报 502。
  2. 接口响应超时。
  3. 接口返回了空数据。
  4. 业务逻辑要求返回空数据。

就需要进行异常处理

  1. 决定骨架屏的状态
  2. 决定下一步的行为(自动重试请求,错误提示,出再试一次按钮,显示兜底内容…)

细心的同学可能已经发现了,正常流程下的接续处理步骤与异常处理是一样的。经过泛化,我们称之为「后处理」吧。

时长处理

我们无法提前知道接口返回需要的时长,如果前端根据接口响应时间来控制开关的状态,那么骨架屏可能会展示很久,也可能会一闪而过,这都不是好的用户体验。

依赖接口响应时长,等于让后端去保证用户体验,这不是很滑稽吗。

严肃的说,不去思考这个问题,就是前端的不作为,用户体验应该由前端兜底。

让我们分别来看看前端如何兜底吧。

image.png

首先看看展示过久的情况,一般接口层会切断超时连接。如果有进一步的需求,前端也能够在请求层统一设置超时阈值。

到达旗帜的时刻,就是需要进行「后处理」的时机了。

再来看一闪而过的情况。 最简单的方案是,在关闭骨架屏时添加一个简单的高度动画过渡。

.skeleton { 
  height: 100px;
  opacity: 1;
  transition: all 0.3s;
}
.fadeOut {
  height: 0;
  opacity: 0;
}

还有一种复杂的方案,完全由前端控制,引入了相当的复杂度,一般不推荐使用。

image.png

上图中,添加了一个绿色的长方形,用来人为控制最小响应时间,不管接口实际返回的耗时。具体逻辑如下。

// 响应时长 R
// 最小响应时长 E

if R < E return E
if R > E return R

是否需要添加这个时机,取决于使用场景,以及「后处理」方案。

例子

让我们用一个例子来说明吧。

绿色方块是一个定高元素,但它的数据需要异步调用接口获取。

但由于异步,页面高度抖动。领导说让你优化一下。很简单,这个时候加一个高度相同的占位元素就搞定了。

image.png

「后处理」可以是

  1. 如果数据获取成功,关闭骨架屏显示,显示取到的数据。
if (showSkeleton) {
  return <Skeleton />
} else {
  return <DataBlock /> 
}
  1. 如果数据获取失败,关闭骨架屏显示,显示兜底内容。
if (showSkeleton) {
  return <Skeleton />
} else {
  return showDataBlock ? <DataBlock /> : <DataAlternative />
}

后来业务逻辑变了,根据接口返回的数据,绿色方块有一定的条件不会出。

因为涉及到了高度,如果直接取消显示,会带来高度抖动。「后处理」的方案就很显然了,由于是定高元素,可以通过动画关闭,延长取消的感知时间。

但是产品还不满意呀,不想要动画效果,但是又要保证不能一闪而过怎么办?

  1. 和产品 PK 一下吧。
  2. PK 不过,那只能通过额外的控制位,兼容接口响应时长的逻辑了。

结尾

骨架屏在很多人看来就只是一个转场。但是其实想要做好并不容易,承前启后的功能定位,天然就会涉及到前端的很多方面,接口请求,视图逻辑,交互体验等。还要控制住代码复杂度,其实并不是一件简单的事情。

之前知乎看到一个问题,用户体验是否应该由前端保证?

这个问题太大了,很难回答。但是在骨架屏这个小点上,我想是的。