写一个关于RN的分秒毫秒组件(组件状态由同一个父组件控制)
介绍一下,就一个界面会一直跑时间,项目有个需求需要用到毫秒级计时器,那我肯定想到用组件了塞,但是组件的状态和组件的数据都是不互通的都是独立的,因此我写了下面这个组件,组件的状态会由父组件控制切记,必须是同一个父组件,因为状态是父组件控制的,如果是多个页面多个父组件的话可以不用看,一键控制所有的组件的开启或者暂停,也可以控制所有组件是否重新启动重新计时,当前也考虑到了如果组件不是同时出现这个数据怎么保持一致的这个方案,组件代码如下
import React, { useState, useEffect, useRef } from 'react'
import { Text, View, Button, StyleSheet } from 'react-native'const Timer = ({ isRunning, elapsedTime, onStart, onStop, firstElapsedTime }) => {const startTimeRef = useRef(null)const animationIdRef = useRef(null)const previousTimeRef = useRef(0)const startTimer = () => {startTimeRef.current = Date.now() - elapsedTimeanimationIdRef.current = requestAnimationFrame(updateTimer)}const stopTimer = () => {cancelAnimationFrame(animationIdRef.current)}const updateTimer = () => {const currentTime = Date.now()const elapsedTime = currentTime - startTimeRef.currentpreviousTimeRef.current = elapsedTimeonStart(elapsedTime)animationIdRef.current = requestAnimationFrame(updateTimer)}useEffect(() => {if (isRunning) {startTimer()} else {stopTimer()}return () => {stopTimer()}}, [isRunning])const handleControl = () => {if (isRunning) {onStop()} else {startTimer()}}const formatTime = (milliseconds) => {const minutes = Math.floor(milliseconds / (60 * 1000))const seconds = Math.floor((milliseconds % (60 * 1000)) / 1000)const millisecondsFraction = Math.floor((milliseconds % 1000) / 10)return ((minutes < 10 ? '0' : '') + minutes + ':' +(seconds < 10 ? '0' : '') + seconds + ':' +(millisecondsFraction < 10 ? '0' : '') + millisecondsFraction)}return (<View><Text>{formatTime(firstElapsedTime)}</Text></View>)
}const ParentComponent = () => {const [timers, setTimers] = useState([{ id: 1, isRunning: false, elapsedTime: 0 },{ id: 2, isRunning: false, elapsedTime: 0 },{ id: 3, isRunning: false, elapsedTime: 0 },])const [nextId, setNextId] = useState(4)const handleStartAll = () => {setTimers(timers.map(timer => ({ ...timer, isRunning: true })))}const handlePauseAll = () => {setTimers(timers.map(timer => ({ ...timer, isRunning: false })))}const handleContinueAll = () => {setTimers(timers.map(timer => ({ ...timer, isRunning: true })))}const handleRestartAll = () => {handlePauseAll()setTimeout(() => {setTimers(timers.map(timer => ({ ...timer, isRunning: true, elapsedTime: timers[0].elapsedTime })))}, 100)}const handleAddTimer = () => {const firstTimerElapsedTime = timers[0].elapsedTime // 获取第一个计时器组件的时间const newTimer = { id: nextId, isRunning: false, elapsedTime: firstTimerElapsedTime }setNextId(nextId + 1)setTimers([...timers, newTimer])}return (<View style={styles.container}><View style={styles.timerContainer}>{timers.map(timer => (<Timerkey={timer.id}isRunning={timer.isRunning}elapsedTime={timer.elapsedTime}onStart={elapsedTime => {const newTimers = [...timers]const index = newTimers.findIndex(t => t.id === timer.id)newTimers[index].elapsedTime = elapsedTimesetTimers(newTimers)}}onStop={() => {const newTimers = [...timers]const index = newTimers.findIndex(t => t.id === timer.id)newTimers[index].isRunning = falsesetTimers(newTimers)}}firstElapsedTime={timers[0].elapsedTime} // 传递第一个计时器的elapsedTime给Timer组件/>))}</View><View style={styles.buttonContainer}><Button title={timers.some(timer => timer.isRunning) ? '全部暂停' : '全部开始'} onPress={timers.some(timer => timer.isRunning) ? handlePauseAll : handleStartAll} /><Button title="继续" onPress={handleContinueAll} /><Button title="重新启动" onPress={handleRestartAll} /><Button title="添加新组件(需要先暂停才行,时间最初为00:00:00,点击开始后时间以第一个组件时间为准)" onPress={handleAddTimer} /></View></View>)
}const styles = StyleSheet.create({container: {flex: 1,justifyContent: 'center',alignItems: 'center',},timerContainer: {marginBottom: 20,},buttonContainer: {flexDirection: 'column',justifyContent: 'space-around',marginTop: 20,},
})export default ParentComponent
上面的组件说明下:(时间会有差别,但是差别不大,基本在几毫秒之内,为了保持数据的一致性,我将都参照第一个组件的时间为准,点击暂停时,所有组件的时间都跟第一个组件保持一致)
点击开始:所有组件开始计时
点击暂停:所有组件全部暂停
点击重启:计时从0开始,重新计时
点击新增组件:需要先暂停才行,因为页面一直在渲染添加不上,我没解决掉,有大佬能解决了更好,还有就是时间以第一个组件显示的时间为准,包括暂停也都是(为了保证所有组件计时的时间的同步)
PS:上面的那个组件展示没必要用循环奥,直接按照下面写也行【如果需要用循环写,也可用循环】
<Timerkey={timers[0].id}isRunning={timers[0].isRunning}elapsedTime={timers[0].elapsedTime}onStart={elapsedTime => {const newTimers = [...timers]const index = newTimers.findIndex(t => t.id === timers[0].id)newTimers[index].elapsedTime = elapsedTimesetTimers(newTimers)}}onStop={() => {const newTimers = [...timers]const index = newTimers.findIndex(t => t.id === timers[0].id)newTimers[index].isRunning = falsesetTimers(newTimers)}}firstElapsedTime={timers[0].elapsedTime} // 传递第一个计时器的elapsedTime给Timer组件/>
上面代码在需要用到组件的地方直接用就行,相当于每个组件都用第一个的状态,或者每个都用自己的状态其实效果是一样的,这种是对于不需要循环在某一个地方使用的情况,就算是循环直接循环三个这样的也行,总之就是这样写也可以,用循环写也可以,这个各位自己定
相关文章:
写一个关于RN的分秒毫秒组件(组件状态由同一个父组件控制)
介绍一下,就一个界面会一直跑时间,项目有个需求需要用到毫秒级计时器,那我肯定想到用组件了塞,但是组件的状态和组件的数据都是不互通的都是独立的,因此我写了下面这个组件,组件的状态会由父组件控制切记,必须是同一个父组件,因为状态是父组件控制的&…...

javascript中字符串处理,常用的方法汇总
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 所属专栏:前端泛海 景天的主页:景天科技苑 文章目录 字符串对象的的相关方法1.获取字符串长度 length2.通过索引获取元素 …...

STM32CubeMX学习笔记14 ---SPI总线
1. 简介 1.1 SPI总线介绍 SPI 是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola(摩托罗拉)首先在其MC68HCXX系列处理器上定义的。 SPI,是一种高速的,全双工,同步的通信总线,并且在…...
Gson(List<Object>转String 、String转List<Object>)
要在Java项目中使用Gson库,你需要添加相应的依赖项。以下是在Maven项目的pom.xml文件中添加Gson依赖的示例: <dependencies><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId>&l…...
uniapp路由跳转的方式
1. uniapp路由跳转的方式 1.1. uni.navigateTo保留当前页面,跳转到应用内的某个页面,使用uni.navigateBack可以返回到原页面。 uni.navigateTo({url:./index/index });注意: (1)页面跳转路径有层级限制,不…...

使用Python模拟绘制自由落体运动过程中的抛物线
目录 一、引言 二、自由落体运动的基本原理 三、使用Python模拟自由落体运动 四、扩展功能:添加速度曲线和动画效果 五、总结与展望 一、引言 自由落体运动是物理学中最基础的运动形式之一,它描述了一个物体在仅受重力作用下的运动轨迹。在这个…...
批量爬取网站图片脚本
不分文件夹 import requests from bs4 import BeautifulSoup import os from concurrent.futures import ThreadPoolExecutordef download_image(img_url):# 检查图片后缀是否为.jpg或.jpegif img_url.lower().endswith((.jpg, .jpeg)):try:img_response requests.get(img_ur…...

scrapy 爬虫:多线程爬取去微博热搜排行榜数据信息,进入详情页面拿取第一条微博信息,保存到本地text文件、保存到excel
如果想要保存到excel中可以看我的这个爬虫 使用Scrapy 框架开启多进程爬取贝壳网数据保存到excel文件中,包括分页数据、详情页数据,新手保护期快来看!!仅供学习参考,别乱搞_爬取贝壳成交数据c端用户登录-CSDN博客 最终…...
网络、UDP编程
1.网络协议模型: OSI协议模型 应用层 实际发送的数据 表示层 发送的数据是否加密 会话层 是否建立会话连接 传输层 数据传输的方式(数据报、流式) 网络层 …...

VSCode安装与使用
1、下载地址:Documentation for Visual Studio Code 在 VS Code 中使用 Python - 知乎 (zhihu.com) 自动补全和智能感知检测、调试和单元测试在Python环境(包括虚拟环境和 conda 环境)之间轻松切换 在 VS Code 中安装插件非常的简单,只需要打开 VS Code…...
进程和线程的区别与联系
进程和线程是计算机系统中两个重要的概念,它们在操作系统中扮演着不同的角色,并有着不同的特点和用途。以下是详细信息: 进程。进程是操作系统中资源分配的基本单位,它包括程序、数据和进程控制块。每个进程都有自己的地址空间&a…...
6、Redis-KV设计、全局命令和安全性
目录 一、value设计 二、Key设计 三、全局命令——针对所有key 四、安全性 一、value设计 ①是否需要排序?需要:Zset ②需要缓存的数据是单个值还是多个值? 单个值:简单值---String;对象值---Hash多个值&#x…...

python之海龟绘图
海龟绘图(turtle)是一个Python内置的绘图库,也被称为“Turtle Graphics”或简称“Turtles”。它采用了一种有趣的绘图方式,模拟一只小海龟在屏幕上爬行,而小海龟爬行的路径就形成了绘制的图形。这种绘图方式最初源自20…...
Java实战:Spring Boot 实现异步记录复杂日志
日志记录是软件开发中非常重要的一环,它可以帮助我们快速定位问题、监控程序运行状态等。在 Spring Boot 应用中,异步记录日志是一种常见的需求。本文将详细介绍如何在 Spring Boot 中实现异步记录复杂日志,包括异步日志的基本原理、实现方式…...

“色狼”用英语怎么说?柯桥日常英语,成人英语口语学习
最近有粉丝问我"色狼"英文翻译是啥 首先声明不是"colour wolf"哈 关于“色狼”的英文表达有很多 快和C姐一起来看看吧! 1.pervert 这个单词的意思是变态、色狼 是对性变态者最直观的描述 He is such a pervert! I saw him lo…...

Docker前后端项目部署
目录 一、搭建项目部署的局域网 二、redis安装 三、MySQL安装 四、若依后端项目搭建 4.1 使用Dockerfile自定义镜像 五、若依前端项目搭建 一、介绍前后端项目 一张图带你看懂ruoyi的前后端项目部署 得出结论:需要4台服务器,都处于同一个局域网中…...
如何快速的搭建一个小程序
要快速搭建一个小程序,你可以按照以下步骤进行: 明确目标和需求:在开始搭建小程序之前,首先明确你的小程序的主要功能、目标用户以及希望实现的业务需求。这将帮助你更好地规划和设计小程序。选择小程序平台:根据你的…...
STM32自学☞AD多通道
涉及到的硬件有:光敏传感器,热敏传感器,红外对射传感器,电位器 通过adc将他们采集的模拟信号转换为数值 ad.c文件 #include "stm32f10x.h" #include "stm32f10x_adc.h" #include "ad.h" #inc…...

微服务之商城系统
一、商城系统建立之前的一些配置 1、nacos Nacos是一个功能丰富的开源平台,用于配置管理、服务发现和注册、健康检查等,帮助构建和管理分布式系统。 在linux上安装nacos容器的命令: docker run --name nacos-standalone -e MODEstandalone …...

安卓玩机工具推荐----高通芯片9008端口读写分区 备份分区 恢复分区 制作线刷包 工具操作解析
上期解析了下adb端口备份分区的有关操作 安卓玩机工具推荐----ADB状态读写分区 备份分区 恢复分区 查看分区号 工具操作解析 在以往的博文中对于高通芯片机型的分区读写已经分享了很多。相关类似博文 安卓备份分区----手动查询安卓系统分区信息 导出系统分区的一些基本操作 …...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...

stm32wle5 lpuart DMA数据不接收
配置波特率9600时,需要使用外部低速晶振...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...

aardio 自动识别验证码输入
技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”,于是尝试整合图像识别与网页自动化技术,完成了这套模拟登录流程。核心思路是:截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...