当前位置: 首页 > news >正文

写一个关于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的分秒毫秒组件(组件状态由同一个父组件控制)

介绍一下,就一个界面会一直跑时间,项目有个需求需要用到毫秒级计时器,那我肯定想到用组件了塞,但是组件的状态和组件的数据都是不互通的都是独立的,因此我写了下面这个组件,组件的状态会由父组件控制切记&#xff0c;必须是同一个父组件&#xff0c;因为状态是父组件控制的&…...

javascript中字符串处理,常用的方法汇总

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;前端泛海 景天的主页&#xff1a;景天科技苑 文章目录 字符串对象的的相关方法1.获取字符串长度 length2.通过索引获取元素 …...

STM32CubeMX学习笔记14 ---SPI总线

1. 简介 1.1 SPI总线介绍 SPI 是英语Serial Peripheral interface的缩写&#xff0c;顾名思义就是串行外围设备接口。是Motorola(摩托罗拉)首先在其MC68HCXX系列处理器上定义的。 SPI&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且在…...

Gson(List<Object>转String 、String转List<Object>)

要在Java项目中使用Gson库&#xff0c;你需要添加相应的依赖项。以下是在Maven项目的pom.xml文件中添加Gson依赖的示例&#xff1a; <dependencies><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId>&l…...

uniapp路由跳转的方式

1. uniapp路由跳转的方式 1.1. uni.navigateTo保留当前页面&#xff0c;跳转到应用内的某个页面&#xff0c;使用uni.navigateBack可以返回到原页面。 uni.navigateTo({url:./index/index });注意&#xff1a; &#xff08;1&#xff09;页面跳转路径有层级限制&#xff0c;不…...

使用Python模拟绘制自由落体运动过程中的抛物线

目录 一、引言 二、自由落体运动的基本原理 三、使用Python模拟自由落体运动 四、扩展功能&#xff1a;添加速度曲线和动画效果 五、总结与展望 一、引言 自由落体运动是物理学中最基础的运动形式之一&#xff0c;它描述了一个物体在仅受重力作用下的运动轨迹。在这个…...

批量爬取网站图片脚本

不分文件夹 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文件中&#xff0c;包括分页数据、详情页数据&#xff0c;新手保护期快来看&#xff01;&#xff01;仅供学习参考&#xff0c;别乱搞_爬取贝壳成交数据c端用户登录-CSDN博客 最终…...

网络、UDP编程

1.网络协议模型: OSI协议模型 应用层 实际发送的数据 表示层 发送的数据是否加密 会话层 是否建立会话连接 传输层 数据传输的方式&#xff08;数据报、流式&#xff09; 网络层 …...

VSCode安装与使用

1、下载地址&#xff1a;Documentation for Visual Studio Code 在 VS Code 中使用 Python - 知乎 (zhihu.com) 自动补全和智能感知检测、调试和单元测试在Python环境(包括虚拟环境和 conda 环境)之间轻松切换 在 VS Code 中安装插件非常的简单&#xff0c;只需要打开 VS Code…...

进程和线程的区别与联系

进程和线程是计算机系统中两个重要的概念&#xff0c;它们在操作系统中扮演着不同的角色&#xff0c;并有着不同的特点和用途。以下是详细信息&#xff1a; 进程。进程是操作系统中资源分配的基本单位&#xff0c;它包括程序、数据和进程控制块。每个进程都有自己的地址空间&a…...

6、Redis-KV设计、全局命令和安全性

目录 一、value设计 二、Key设计 三、全局命令——针对所有key 四、安全性 一、value设计 ①是否需要排序&#xff1f;需要&#xff1a;Zset ②需要缓存的数据是单个值还是多个值&#xff1f; 单个值&#xff1a;简单值---String&#xff1b;对象值---Hash多个值&#x…...

python之海龟绘图

海龟绘图&#xff08;turtle&#xff09;是一个Python内置的绘图库&#xff0c;也被称为“Turtle Graphics”或简称“Turtles”。它采用了一种有趣的绘图方式&#xff0c;模拟一只小海龟在屏幕上爬行&#xff0c;而小海龟爬行的路径就形成了绘制的图形。这种绘图方式最初源自20…...

Java实战:Spring Boot 实现异步记录复杂日志

日志记录是软件开发中非常重要的一环&#xff0c;它可以帮助我们快速定位问题、监控程序运行状态等。在 Spring Boot 应用中&#xff0c;异步记录日志是一种常见的需求。本文将详细介绍如何在 Spring Boot 中实现异步记录复杂日志&#xff0c;包括异步日志的基本原理、实现方式…...

“色狼”用英语怎么说?柯桥日常英语,成人英语口语学习

最近有粉丝问我"色狼"英文翻译是啥 首先声明不是"colour wolf"哈 关于“色狼”的英文表达有很多 快和C姐一起来看看吧&#xff01; 1.pervert 这个单词的意思是变态、色狼 是对性变态者最直观的描述 He is such a pervert&#xff01; I saw him lo…...

Docker前后端项目部署

目录 一、搭建项目部署的局域网 二、redis安装 三、MySQL安装 四、若依后端项目搭建 4.1 使用Dockerfile自定义镜像 五、若依前端项目搭建 一、介绍前后端项目 一张图带你看懂ruoyi的前后端项目部署 得出结论&#xff1a;需要4台服务器&#xff0c;都处于同一个局域网中…...

如何快速的搭建一个小程序

要快速搭建一个小程序&#xff0c;你可以按照以下步骤进行&#xff1a; 明确目标和需求&#xff1a;在开始搭建小程序之前&#xff0c;首先明确你的小程序的主要功能、目标用户以及希望实现的业务需求。这将帮助你更好地规划和设计小程序。选择小程序平台&#xff1a;根据你的…...

STM32自学☞AD多通道

涉及到的硬件有&#xff1a;光敏传感器&#xff0c;热敏传感器&#xff0c;红外对射传感器&#xff0c;电位器 通过adc将他们采集的模拟信号转换为数值 ad.c文件 #include "stm32f10x.h" #include "stm32f10x_adc.h" #include "ad.h" #inc…...

微服务之商城系统

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

安卓玩机工具推荐----高通芯片9008端口读写分区 备份分区 恢复分区 制作线刷包 工具操作解析

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

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...

tomcat指定使用的jdk版本

说明 有时候需要对tomcat配置指定的jdk版本号&#xff0c;此时&#xff0c;我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...