开发环境时Taro+React Native+TypeScript
TypeScript
export interface TimerRef{
timeShow: ()=>{};
getCurrentTime: () => number;
}
// 修改这里:添加 props 参数,即使不使用也要保留位置
const Timer = forwardRef<TimerRef, {}>((props, ref) => {
const [count, setCount] = useState(0);
const timerRef = useRef<NodeJS.Timeout | null>(null);
const memoryName = 'Time Pace'
// 暴露方法给父组件
useImperativeHandle(ref, ()=>({
timeShow: ()=>{
console.log("定时器的当前时间: current time = ", count)
console.log("memoryName = ", memoryName)
},
getCurrentTime: ()=>{
return count
}
}))
const startTimer = () => {
// 如果已经有定时器在运行,先清除
if (timerRef.current !== null) {
clearInterval(timerRef.current);
}
timerRef.current = setInterval(() => {
setCount(prev => prev + 1);
}, 1000);
};
const stopTimer = () => {
if (timerRef.current !== null) {
clearInterval(timerRef.current);
timerRef.current = null; // 清除后重置为 null
}
};
useEffect(() => {
return () => {
if (timerRef.current !== null) {
clearInterval(timerRef.current);
}
};
}, []);
return (
<div>
<p>计数: {count}</p>
<button className='btn' style={{marginRight: 20}} onClick={startTimer}>开始</button>
<button className='btn' onClick={stopTimer}>停止</button>
</div>
);
})
TypeScript
import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef } from 'react'
import { View, Text, Button } from '@tarojs/components'
import './index.scss'
interface IProps{
color: string;
size: string;
originalPrice?: string;
description?: string;
likeStar?: string;
price: number;
}
const DressPaper = (props:IProps) => {
const [price, setPrice] = useState(props.price)
const [likeStar, setLikeStar] = useState(props.likeStar || 'star, ')
const priceRef = useRef<HTMLSpanElement>(null)
const preStarsNumRef = useRef(0)
const timeRef = useRef<TimerRef>(null)
// 改变价格
const changeDressPrice = ()=>{
setPrice(prePrice =>{
return ++prePrice
});
// 使用useRef动态改变元素的样式
if(priceRef.current){
// const element = priceRef.current as unknown as HTMLElement;
priceRef.current.style.color = 'blue'
}
}
// 使用ref存储上一次的值
// 增加like Star并记录上一次增加后的次数
const addLikeStar = ()=>{
setLikeStar(preLikeStar => {
return preLikeStar + 'star, '
})
// useRef修饰的值跨越整个生命周期都不会改变,但当值改变时也可以更新在页面中
preStarsNumRef.current++
}
//子组件的事件处理
const handleSubShow = ()=>{
console.log("通过ref在子组件中获取的当前时间 current time = ", timeRef.current?.getCurrentTime())
timeRef.current?.timeShow()
}
return (<View>
<View className='container'>
<Text ref={priceRef} className='txt'>Price: {'$' + price}</Text>
<Text className='txt'>{likeStar}</Text>
<Text className='txt'>上一次增加的star个数为:{preStarsNumRef.current}</Text>
</View>
<View>
<Button className='btn' onClick={changeDressPrice}>change price</Button>
<Button className='btn' onClick={addLikeStar}>add like star</Button>
</View>
<View style={{backgroundColor: '#cc9999'}}>
<Text className='txt'>
使用useRef做父子组件间的通信,存储定时器, 组件销毁时清除定时器
</Text>
<Timer ref={timeRef}></Timer>
<Button className='btn' onClick={handleSubShow}>
父组件调用子组件方法,修改子组件的属性
</Button>
</View>
</View>
);
}
export default DressPaper;
TypeScript
import UseRefComponent from "../Hooks/UseRef";
<UseRefComponent color='blue' size='m' price={20}></UseRefComponent>
下面的是样式scss文件
TypeScript
.container {
display: flex;
flex-direction: column;
padding: 20px;
background-color: #ADD8E6;
margin-bottom: 40px;
}
.txt {
height: 44px;
padding: 15px 100px;
margin-bottom: 7px;
background-color: #FFE4E1;
font-size: 26px;
}
.btn {
height: 64px;
// padding: 15px 100px 15px 100px;
margin-bottom: 7px;
background-color: #D8BFD8;
font-size: 28px;
}
.buttonContainer {
display: flex;
flex-direction: row;
justify-content: space-around;
margin-bottom: 20px;
}
.input {
background-color: white;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}