【React Native】渐变骨架屏组件SkeletonElement

React Native 渐变骨架屏组件 SkeletonElement 使用指南

一、前言

在移动端开发中,数据加载过程中的空白等待会显著降低用户体验。骨架屏(Skeleton Screen) 是一种广受推崇的加载策略:它通过渲染与真实内容结构一致的灰色占位块,在数据返回前给予用户明确的视觉反馈。

本文提供一个轻量、高性能、支持自定义样式的 SkeletonElement 组件,适用于任何需要占位展示的 UI 元素。


二、组件特性

  • 完全自定义样式 :通过 style 属性控制尺寸、方向、间距等
  • 流畅渐变动画 :使用 Animated 实现原生驱动的高帧率闪烁效果
  • 轻量无依赖:仅基于 React Native 内置模块,零第三方依赖
  • 灵活配色:支持自定义背景色和高亮色
  • 自动清理:组件卸载时自动停止动画,防止内存泄漏

三、快速上手

tsx 复制代码
<View>
  {/* 标题骨架 */}
  <SkeletonElement style={{ height: 24, width: '80%', marginBottom: 16 }} />
  
  {/* 多行文本骨架 */}
  <SkeletonElement style={{ height: 16, width: '100%', marginBottom: 8 }} />
  <SkeletonElement style={{ height: 16, width: '90%', marginBottom: 8 }} />
  <SkeletonElement style={{ height: 16, width: '95%' }} />
  
  {/* 按钮骨架 */}
  <SkeletonElement 
    style={{ 
      height: 48, 
      width: '50%', 
      borderRadius: 24, 
      alignSelf: 'center',
      marginTop: 20 
    }} 
  />
</View>

四、API 说明

Props

属性 类型 默认值 说明
style StyleProp<ViewStyle> undefined 自定义骨架样式(宽高、方向、圆角等)
backgroundColor string #E4E4E4 骨架背景色
highlightColor string #D0D0D0 高亮闪烁色(较背景色稍亮)
speed number 1600 完整闪烁周期(毫秒),值越小动画越快

五、源码解析

核心逻辑

  1. 动画驱动 :使用 useRef(new Animated.Value(0.4)) 创建不触发重渲染的动画值
  2. 循环闪烁 :通过 Animated.loop + Animated.sequence 实现"暗→亮→暗"的循环
  3. 性能优化 :启用 useNativeDriver: true,动画在原生线程运行
  4. 资源清理useEffect 返回清理函数,确保组件卸载时停止动画

关键代码片段

ts 复制代码
const opacityValue = useRef(new Animated.Value(0.4)).current;

useEffect(() => {
  Animated.loop(
    Animated.sequence([
      Animated.timing(opacityValue, { toValue: 1, ... }),
      Animated.timing(opacityValue, { toValue: 0.4, ... })
    ])
  ).start();

  return () => opacityValue.stopAnimation();
}, [opacityValue, speed]);

六、完整源码

tsx 复制代码
import React, {useEffect, useRef} from 'react';
import {Animated, Easing, StyleProp, View, ViewStyle} from 'react-native';

interface SkeletonElementProps {
  style?: StyleProp<ViewStyle>;
  backgroundColor?: string;
  highlightColor?: string;
  speed?: number;
}

export const SkeletonElement: React.FC<SkeletonElementProps> = ({
  style,
  backgroundColor = '#E4E4E4',
  highlightColor = '#D0D0D0',
  speed = 1600,
}) => {
  const useSkeletonAnimation = (speed: number) => {
    const opacityValue = useRef(new Animated.Value(0.4)).current;

    useEffect(() => {
      Animated.loop(
        Animated.sequence([
          Animated.timing(opacityValue, {
            toValue: 1,
            duration: speed / 2,
            easing: Easing.inOut(Easing.ease),
            useNativeDriver: true,
          }),
          Animated.timing(opacityValue, {
            toValue: 0.4,
            duration: speed / 2,
            easing: Easing.inOut(Easing.ease),
            useNativeDriver: true,
          }),
        ]),
      ).start();

      // 返回清理函数
      return () => {
        opacityValue.stopAnimation();
      };
    }, [opacityValue, speed]);

    return opacityValue;
  };

  const opacityValue = useSkeletonAnimation(speed);

  // 合并样式
  const skeletonStyle: ViewStyle = {
    backgroundColor,
    overflow: 'hidden',
    position: 'relative',
    ...(style as ViewStyle),
  };

  // 添加渐变动画效果
  const highlightOverlay = (
    <Animated.View
      style={{
        position: 'absolute',
        top: 0,
        left: 0,
        right: 0,
        bottom: 0,
        backgroundColor: highlightColor,
        opacity: opacityValue,
      }}
    />
  );

  return <View style={skeletonStyle}>{highlightOverlay}</View>;
};

💡 提示:将此组件与条件渲染结合,即可实现优雅的数据加载过渡:

tsx 复制代码
{loading ? <SkeletonElement style={{ height: 200 }} /> : <RealContent />}

相关推荐
lbb 小魔仙4 天前
鸿蒙跨平台项目实战篇03:React Native Bundle增量更新详解
react native·react.js·harmonyos
2301_796512524 天前
【精通篇】打造React Native鸿蒙跨平台开发高级复合组件库开发系列:点击组件(跳转快应用)
javascript·react native·react.js·ecmascript·harmonyos
2301_796512524 天前
【精通篇】打造React Native鸿蒙跨平台开发高级复合组件库开发系列:Sidebar 侧边导航(绑定当前选中项的索引)
javascript·react native·react.js·ecmascript·harmonyos
lbb 小魔仙4 天前
鸿蒙跨平台项目实战篇01:React Native Bundle版本管理详解
react native·react.js·harmonyos
2301_796512524 天前
【精通篇】打造React Native鸿蒙跨平台开发高级复合组件库开发系列:Pagination 分页(绑定当前页码)
javascript·react native·react.js·ecmascript·harmonyos
星空22234 天前
鸿蒙跨平台实战:React Native 在 OpenHarmony 上的 PixelFormat 图片格式处理
react native·华为·harmonyos
getyefang4 天前
react-native使用字体库如何在安卓显示
javascript·react native·react.js
星空22234 天前
鸿蒙跨平台实战day47:React Native在OpenHarmony上的Font自定义字体注册详解
react native·华为·harmonyos
Cxiaomu5 天前
React Native项目(Android )集成虹软 ArcFace(人脸识别增值版 5.0 Java)
android·java·react native