React Native Web ActivityIndicator 组件完全指南:Props 详解、SVG 实现原理与实战示例
【免费下载链接】react-native-webCross-platform React UI packages项目地址: https://gitcode.com/gh_mirrors/re/react-native-web
ActivityIndicator 是 react-native-web 提供的跨平台加载指示器组件,用于在 Web 页面中展示"正在加载/处理中"的状态。本文基于 react-native-web 官方文档与源码,完整讲解其全部 Props 的默认值与行为、底层基于 SVG 与 CSS 动画的实现原理、无障碍(ARIA)设计,并附上可直接运行的实战示例与测试验证方式,帮助你准确、无障碍地使用该组件。
组件概览与基本用法
ActivityIndicator 在 react-native-web 中被设计为与 React Native 原生端 API 完全对齐的组件:从'react-native'导入后即可直接使用,渲染结果是一个具有progressbar角色语义的 DOM 元素。
import { ActivityIndicator } from 'react-native'; <ActivityIndicator {...props} />;在 react-native-web 组件导出入口 中可以看到,ActivityIndicator与其他组件(如View、Text、Button)一同从./exports/ActivityIndicator导出。它没有任何必填参数——所有 Props 均有默认值,因此最简单的用法就是直接渲染<ActivityIndicator />。
API:Props 全解析
以下参数与官方文档完全一致,并补充了各参数的实现细节与取值说明。
...ViewProps(继承自 View)
?ViewProps—— ActivityIndicator 支持 View 组件的全部 Props。
从 实现源码 的类型定义可以确认:
type ActivityIndicatorProps = { ...ViewProps, animating?: boolean, color?: ?string, hidesWhenStopped?: boolean, size?: 'small' | 'large' | number };这意味着你可以直接向它传递style、accessibilityLabel、accessibilityLiveRegion、nativeID、testID、dataSet、onBlur、onFocus等 View 属性,它们会被透传到最外层的容器元素上。
animating
类型:?boolean,默认值true。
设置指示器是否处于动画状态。源码中通过解构赋值给出默认值:
const { animating = true, ... } = props;当animating={false}时,动画通过animationPlayState: 'paused'被暂停,指示器停止旋转。
color
类型:?string,默认值"#1976D2"(Material Design 蓝色)。
设置指示器的颜色。该颜色会作为stroke应用到 SVG 圆环的两个<circle>上(见下文实现原理)。
hidesWhenStopped
类型:?boolean,默认值true。
设置指示器在停止动画时是否隐藏。仅在animating={false}时生效,此时会额外追加visibility: 'hidden'样式;若同时设置hidesWhenStopped={false},则指示器会停留在页面上但保持静止。
size
类型:?("small" | "large" | number),默认值"small"。
设置指示器的尺寸:
| 取值 | 渲染尺寸 | 说明 |
|---|---|---|
"small" | 20 × 20 px | 默认值 |
"large" | 36 × 36 px | 大尺寸 |
number(如30) | 宽高均为该数值 | 任意像素尺寸,通过内联height/width生效 |
源码中定义了两种预置尺寸,数值型尺寸则直接转为内联样式:
const indicatorSizes = StyleSheet.create({ small: { width: 20, height: 20 }, large: { width: 36, height: 36 } }); // 渲染时: typeof size === 'number' ? { height: size, width: size } : indicatorSizes[size]底层实现原理:SVG 圆环 + CSS 关键帧动画
与原生端使用平台原生控件不同,react-native-web 的 ActivityIndicator 完全基于内联 SVG + CSS 动画实现,源码位于 ActivityIndicator 实现。
SVG 双圆环结构
组件渲染一个viewBox="0 0 32 32"的 SVG,其中包含两个同心圆(圆心cx=16、cy=16,半径r=14,strokeWidth=4):
- 底层圆环:
opacity: 0.2,用于绘制浅色轨道; - 上层圆环:
strokeDasharray: 80、strokeDashoffset: 60,即只有部分弧线可见,从而呈现"弧段旋转"的经典加载效果。
const createSvgCircle = (style) => ( <circle cx="16" cy="16" fill="none" r="14" strokeWidth="4" style={style} /> ); const svg = ( <svg height="100%" viewBox="0 0 32 32" width="100%"> {createSvgCircle({ stroke: color, opacity: 0.2 })} {createSvgCircle({ stroke: color, strokeDasharray: 80, strokeDashoffset: 60 })} </svg> );CSS 旋转动画
动画通过 StyleSheet 中定义的 CSS 关键帧完成,一个完整周期 0.75 秒、匀速、无限循环:
animation: { animationDuration: '0.75s', animationKeyframes: [ { '0%': { transform: 'rotate(0deg)' } }, { '100%': { transform: 'rotate(360deg)' } } ], animationTimingFunction: 'linear', animationIterationCount: 'infinite' }, animationPause: { animationPlayState: 'paused' }, hidesWhenStopped: { visibility: 'hidden' }三种状态的样式组合逻辑如下:
animating={true}:正常播放animation;animating={false}:追加animationPause,动画暂停;animating={false} && hidesWhenStopped:再追加hidesWhenStopped,visibility: hidden使其不可见。
无障碍(ARIA)语义
组件外层容器被渲染为role="progressbar",并带有aria-valuemin={0}与aria-valuemax={1},向屏幕阅读器表明这是一个不确定进度的加载指示器。由于animating只影响视觉动画而非语义,因此不会移除 ARIA 角色。从 组件测试快照 中可以看到完整的 DOM 输出:
<div aria-valuemax="1" aria-valuemin="0" role="progressbar"> <div class="... r-animationDuration-17bb2tj ..."> <svg height="100%" viewBox="0 0 32 32" width="100%"> <circle cx="16" cy="16" fill="none" r="14" stroke-width="4" style="stroke: #1976D2; opacity: 0.2;" /> <circle cx="16" cy="16" fill="none" r="14" stroke-width="4" style="stroke: #1976D2; stroke-dasharray: 80; stroke-dashoffset: 60;" /> </svg> </div> </div>实战示例:尺寸、颜色与动态切换
官方示例位于 react-native-web-examples 的 activity-indicator 页面,展示了不同颜色、尺寸组合以及通过animating状态控制的动态切换,是理解组件用法的直接参考:
import { ActivityIndicator, StyleSheet, View } from 'react-native'; import React from 'react'; export default function ActivityIndicatorPage() { const [animating, setAnimating] = React.useState(true); // 每 2 秒切换一次动画状态,模拟加载开始/结束 React.useEffect(() => { const interval = setInterval(() => { setAnimating(!animating); }, 2000); return () => { clearInterval(interval); }; }, [animating]); return ( <View> <View style={styles.row}> {/* 默认配置 */} <ActivityIndicator style={styles.item} /> {/* 停止动画但不隐藏 */} <ActivityIndicator animating={false} hidesWhenStopped={false} style={styles.item} /> {/* 由定时器控制的动画状态 */} <ActivityIndicator animating={animating} hidesWhenStopped={false} style={styles.item} /> </View> <View style={styles.row}> <ActivityIndicator color="#1DA1F2" size="small" style={styles.item} /> <ActivityIndicator color="#17BF63" size={20} style={styles.item} /> </View> <View style={styles.row}> <ActivityIndicator color="#FFAD1F" size="large" style={styles.item} /> <ActivityIndicator color="#F45D22" size={36} style={styles.item} /> </View> <View style={styles.row}> <ActivityIndicator color="#794BC4" size={60} style={styles.item} /> </View> </View> ); }几个值得注意的实战要点:
- 自定义颜色:
color支持任意 CSS 颜色字符串,如示例中的 Twitter 蓝#1DA1F2、Twitter 绿#17BF63等; - 任意尺寸:
size可传任意数字,如20、36、60,对应渲染为等宽等高的指示器; - 停止但保留占位:当需要"加载完成但保留视觉占位"时,使用
animating={false} + hidesWhenStopped={false}; - 内联样式透传:
style(如示例中的paddingHorizontal)会合并到外层容器,用于间距布局。
该示例页面可以通过官方文档内嵌的 CodeSandbox 交互运行(由 macros.html 中的 codesandbox 宏 注入),也可以在本地启动 examples 项目后访问:
cd packages/react-native-web-examples npm install npm run dev测试验证:组件行为的回归保障
组件行为由 index-test.js 测试套件 覆盖,主要验证内容包括:
- 动画与隐藏状态:
animating为true/false时的渲染输出;hidesWhenStopped为true/false时的快照差异; - 颜色:
color="red"时 SVG 中<circle>的stroke为red; - 尺寸:
size="large"与size={30}(数值)分别生成预置类名与内联height/width: 30px; - View Props 透传:
accessibilityLabel、accessibilityLiveRegion、dataSet、nativeID、testID、style、ref、onBlur、onFocus均按预期渲染或触发。
从快照文件可以看出,数值尺寸size={30}时内联样式为style="height: 30px; width: 30px;",而字符串尺寸则生成原子 CSS 类名(如r-width-19wmn03),这正是 react-native-web StyleSheet 编译机制(将 React Native 样式编译为原子 CSS)在组件上的体现。
小结
ActivityIndicator 是 react-native-web 中一个"小而完整"的组件:API 与 React Native 对齐、零依赖 SVG 渲染、CSS 关键帧驱动动画、内置 ARIA 无障碍语义,并有完整测试覆盖。实际开发时只需记住五个核心 Props(animating、color、hidesWhenStopped、size、以及继承自 View 的其余属性),即可在 Web 端复刻原生加载体验。相关源码、测试与示例均可在本仓库的 组件实现、测试用例 与 示例页面 中继续深入研读。
【免费下载链接】react-native-webCross-platform React UI packages项目地址: https://gitcode.com/gh_mirrors/re/react-native-web
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考