自动生成跨多端骨架屏

概念以及背景

Skeleton Screen,中文称之为骨架屏。表示在页面数据没有加载完成之前,用一些简单的图形描绘页面内容的大致布局,让用户感知页面正在加载;当数据加载完成后,用真实的数据渲染页面,把它替换掉。

在骨架屏诞生之前,业界大多数都是用菊花图之类的loading效果去做数据等待期的加载效果展示,但是这种效果对于用户体验却未必优秀,当用户聚焦于菊花图时,就像学生盯着下课前的5分钟,感知上时间会变慢,很容易滋生焦躁情绪,如果是弱网情况下可能用户直接就关闭页面了。

如果我们能在页面真实内容呈现之前先把页面内容的轮廓展示出来,然后再逐步展示真正的内容,这样既能给用户一种内容正在被加载即将呈现出来的期待,也能降低用户等待过程中的焦躁情绪,同时还能使页面加载的过程变得更加丝滑,感官上会更加自然流畅,而骨架屏就是为此而生。

如何生成骨架屏

要生成骨架屏,我们可以怎么做呢?
答案一:手写骨架屏代码,这种方案可能大家的反应是下面这样

答案二:自动生成?

自动生成骨架屏看起来似乎很难做到,主要困难点在于:

  • 页面真实内容结构难以自动获取

  • 如果拿到了页面结构,如何根据页面结构生成骨架屏的节点和样式

这两个问题目前采用一些前端技术其实也可以解决,我写了一个webpack插件skeleton-webpack-plugin可以实现在你本地运行dev server预览页面的时候生成该页面骨架屏的html与css,总体思路如下图所示:

但是到这里我们只是生成了在h5环境可以使用的骨架屏,回到我们的主题,我们想要的是跨多端哦,也就是说iOS,android,小程序等等我全都要,这个又该如何实现呢?

skeleton-weex-plugin

目前我们团队内部在weex的基础上开发了一套跨端开发框架,借助这套框架我们可以基本实现在iOS,android,小程序等多端实现一套代码复用,但是目前尚未开源,所以我先借用weex作为跨多端的技术实现以及vue作为dsl,如果你的团队也是采用类weex技术方案,那么你可以直接复用我的代码。

对于生成多端骨架屏的问题,我的解决方案是skeleton-weex-plugin,它是skeleton-webpack-plugin的一个插件。
如前所述,skeleton-webpack-plugin可以生成对应页面骨架屏的html与css,那么进一步思考,如果我们可以将这份html与css转化成weex的代码,这样就可以实现在一套骨架屏在多端都可以呈现。skeleton-weex-plugin的实现思路如下图所示:

它会在你对应的页面目录下生成一个skeleton.vue的文件,如下所示:

<template>
<div v-if="isShow" class="skeleton-wrapper">
<div>skeleton content</div>
</div>
</template>
<script>
export default {
  name: "Skeleton",
  props: {
    isShow: {
      type: Boolean,
      default: false
    }
  }
}
</script>
<style scoped>
skeleton style content
</style>
复制代码

这样你就可以把它当成组件来引用,并控制它的显示和隐藏。可以来看下小桔养车首页转化出来的一个效果图:


可以说相似度还是比较高的。这样似乎可以坐下来喝杯红酒了:

但是这样就完美了么?

后续的优化之路

虽然我们初步达成了预期的实现目标,但是还存在几个比较重要的问题。

  • h5页面还是会有白屏时间,因为这种方式在js bundle加载完成前还是展示的空白页。

    这个问题的解决思路是你可以将骨架屏的html与css直接打到静态的页面模版html上,然后在js bundle加载完成后删除该节点

  • 引入的骨架屏组件会导致js bundle体积增大。

    目前我在生成weex代码过程中已经做了很多的精简工作,比如只生成在viewport可见区域内元素的骨架屏,删除一些不必要的样式等,后续也会看看是否还有可以继续精简的代码。

  • native端渲染时在页面 js bundle加载完成前页面也会是白屏。

    这个问题的解决思路是可以用骨架屏的预览页截屏生成一张图片,然后native端在js bundle加载完成前展示这张图片即可填充白屏时间。

所以,我们还能也必须可以做的更好

这里是利用weex实现了跨多端的诉求,但是如果要拓展到其他技术栈其实本质思想也是一样,只需要将骨架屏的html与css抽象语法树转化成对应技术栈的实现即可,即使生成纯native的代码也并非不能做到,欢迎大家去贡献插件。

相关代码

如果喜欢请用star砸我吧。

1.手动编写骨架静态布局文件+动画库 实现方式:通过编写单独的XML布局文件,使用<shape>、<View>等基础控件模拟骨架块的形状和位置,通过ViewStub或控制Visibility的方式在数据加载前后进行切换,同时结合动画库(如shimmer-android)实现骨架的闪烁动画。 优点:实现简单,学习成本低。性能最好,无反射和运行时布局解析开销。布局精准,与真实UI布局可高度一致。 缺点:开发效率极低,每个页面都需要单独编写一套骨架布局,维护成本高。灵活性差,不易适配多种状态(如错误页、无数据页)。与真实布局是分离的,一旦真实布局修改,骨架布局也需同步修改,容易不一致。 适用于中小型项目,尤其是页面结构较为固定、对骨架样式有定制需求的 App。 2.使用第三方开源库 主要有两类,一类需要用特定布局包裹原来布局,如Skeletonlayout,一类无需操作view只需绑定view的id,如Skeleton。前者通常提供自定义ViewGroup(如SkeletonLayout)或RecyclerView的适配器(如ShimmerRecyclerView),通过代码的方式,自动将普通布局转换为骨架。后者无需使用对应的ViewGroup包裹原布局,只需要在代码中绑定id即可生成骨架。 优点:开发效率高,通常通过简单包装即可实现,无需编写额外XML。一致性较好,因为是基于原布局生成,能最大程度还原UI结构。通常自带闪烁动画,效果丰富。 缺点:兼容性和稳定性依赖第三方库,可能存在未知BUG。部分库使用了反射等黑科技,可能带来性能损耗和兼容性问题。自定义化程度可能受库的能力限制,大多不支持对于自定义view的骨架生成。使用场景受限,只能针对于xml中已有得view进行骨架覆盖,对于动态加载进当前布局得view没有识别功能。 适用于追求开发效率、项目周期紧张的中大型项目。 3.WebView+前端技术 使用 WebView 加载前端骨架结构是一种适用于 Hybrid 架构 App 的实现方式。其核心思想是前端通过 HTML/CSS/JS 构建骨架结构,并将其打包为 HTML 文件嵌入到 App 的 WebView 中。在数据加载期间展示骨架,加载完成后切换为真实内容。 优点:与前端技术栈统一,便于实现统一的设计语言和响应式布局。与前端开发流程一致,适配性强,适合需要统一 Web 与 Native 骨架样式的项目。 缺点: WebView 初始化耗时较长、与原生交互复杂(需处理 JSBridge)、资源占用较大等问题。该方案适用于 Hybrid 架构 App 或需要与 Web 端共用骨架结构的项目,尤其是对端一致性要求较高的场景。 适用于 Hybrid 架构 App 或需要与 Web 端共用骨架结构的项目,尤其是对端一致性要求较高的场景 这是我目前得技术方案调研,你也看到了有错误,比如skeleton这个库本身也需要自己写骨架得view只是多了bind和动画行为,如果按照我的内在逻辑,应该是归属于法1的吧?其次我觉得这个技术方案调研可能写的也不是很好,帮我修改优化
最新发布
09-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值