前言
随着 PWA 技术的广泛应用,Web 应用程序的用户体验也越来越受到关注。其中,骨架屏(Skeleton Screen)作为一种在页面加载过程中显示空白占位符,弱化用户等待时间的方式,逐渐成为优化用户体验的有效手段。本文将针对前端开发人员,介绍如何在 PWA 中实现骨架屏的自动生成。
什么是骨架屏?
骨架屏指在页面完成渲染之前,通过一个预置的页面布局(通常是灰色的)来占位,弱化用户等待时间。它可以有效地降低用户等待页面加载的焦虑和不安全感,提高用户体验。
这里是一个简单的骨架屏生成样例:

如何实现骨架屏?
下面我们将介绍如何在 PWA 中实现骨架屏的自动生成。
第一步:创建骨架屏组件
首先,我们需要创建一个骨架屏组件,来承载预置的页面布局。在这个组件中,我们可以添加一些占位符元素(比如灰色的矩形框),以及一些占位文本(比如 Lorem ipsum)等。
// www.javascriptcn.com code example
<!-- 骨架屏组件 -->
<template>
<div class="skeleton">
<div class="content">
<!-- 内容占位符 -->
<div class="place-holder" v-for="index in 6" :key="index"></div>
<!-- 文本占位符 -->
<div class="text-placeholder">
<div class="place-holder" v-for="index in 4" :key="index"></div>
</div>
</div>
</div>
</template>
<!-- 样式 -->
<style>
.skeleton {
background-color: #f2f2f2;
}
.content {
padding: 20px;
}
.place-holder {
background-color: #e0e0e0;
height: 20px;
margin-bottom: 10px;
border-radius: 4px;
}
.text-placeholder {
display: flex;
flex-direction: column;
}
.text-placeholder .place-holder {
height: 10px;
margin-bottom: 5px;
border-radius: 4px;
}
</style>第二步:创建骨架屏生成函数
接下来,我们需要创建一个骨架屏生成函数,来根据组件的层级结构和样式信息,自动地生成骨架屏布局。这里我们可以借助 Vue 的 mixin 功能,将骨架屏生成函数挂载到全局,方便在任意组件中调用。
// www.javascriptcn.com code example
// 骨架屏生成函数
const generateSkeleton = (component) => {
const el = document.createElement('div')
const props = Object.assign({}, component.props || {}, {
isLoading: true
})
const instance = new Vue({
props,
render(h) {
const data = {
attrs: this.$attrs,
on: this.$listeners
}
return h(component, data)
}
}).$mount(el)
return el
}
// 骨架屏 mixin
const SkeletonMixin = {
methods: {
$generateSkeleton(component) {
const skeleton = generateSkeleton(component)
this.$el.appendChild(skeleton)
return skeleton
}
}
}
// 将骨架屏 mixin 挂载到全局 Vue 中
Vue.mixin(SkeletonMixin)第三步:使用骨架屏生成函数
最后,我们可以在需要显示骨架屏的组件中,调用骨架屏生成函数,来自动生成骨架屏布局。比如下面这个示例,我们可以在列表组件中调用 $generateSkeleton 函数,来自动生成骨架屏布局。
// www.javascriptcn.com code example
<!-- 列表组件 -->
<template>
<ul>
<li v-for="item in items" :key="item.id">
<div class="image">
<img :src="item.image" alt="">
</div>
<div class="content">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
<span>{{ item.date }}</span>
</div>
</li>
</ul>
</template>
<!-- 样式 -->
<style>
ul {
list-style: none;
padding: 0;
margin: 0;
}
li {
display: flex;
margin-bottom: 20px;
}
.image {
width: 150px;
height: 150px;
background-color: #e0e0e0;
border-radius: 4px;
overflow: hidden;
}
.image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.content {
margin-left: 20px;
}
h3 {
background-color: #e0e0e0;
height: 20px;
width: 60%;
margin-bottom: 10px;
border-radius: 4px;
}
p {
background-color: #e0e0e0;
height: 10px;
margin-bottom: 5px;
border-radius: 4px;
}
span {
background-color: #e0e0e0;
height: 10px;
width: 30%;
border-radius: 4px;
}
</style>
<!-- 逻辑 -->
<script>
import Skeleton from './Skeleton.vue'
export default {
data() {
return {
items: [],
isLoading: true
}
},
mounted() {
// 模拟异步请求数据
setTimeout(() => {
this.items = [
{
id: 1,
title: 'Lorem ipsum dolor sit amet',
description:
'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam',
date: '2020-10-01',
image:
'https://cdn.jsdelivr.net/gh/html-css-js/1591914761487.static/res1.jpg'
},
{
id: 2,
title: 'Consectetur adipiscing elit',
description:
'Eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris',
date: '2020-10-02',
image:
'https://cdn.jsdelivr.net/gh/html-css-js/1591914761487.static/res2.jpg'
},
{
id: 3,
title: 'Sed do eiusmod tempor',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',
date: '2020-10-03',
image:
'https://cdn.jsdelivr.net/gh/html-css-js/1591914761487.static/res3.jpg'
}
]
this.isLoading = false
}, 3000)
},
computed: {
content() {
if (this.isLoading) {
return this.$generateSkeleton(Skeleton) // 生成骨架屏布局
} else {
return this.items
}
}
}
}
</script>上述示例中,为了模拟异步请求数据,在 mounted 钩子中使用了一个 setTimeout,模拟 3 秒后获取数据成功,此时将 isLoading 置为 false,并返回真实数据。而在 content 计算属性中,如果 isLoading 为 true,则调用 $generateSkeleton 函数,生成骨架屏布局,否则返回真实数据。
小结
本文介绍了如何在 PWA 中实现骨架屏自动生成的方法,通过创建骨架屏组件、骨架屏生成函数和骨架屏 mixin,我们可以方便地在需要优化用户体验的地方使用骨架屏,来降低用户等待时间和焦虑感,提高用户体验。在实际开发中,可以根据具体的场景和需求,灵活地运用此方法。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67c14577314edc2684919942