从Vue到React:重构双击爱心动画组件的7个关键技术决策

1. 状态管理:从响应式数据到Hooks的思维转换

重构双击爱心组件,第一个要啃的硬骨头就是状态管理。在Vue里,我们习惯了用 refreactive 声明响应式数据,数据一变,视图自动更新,非常直观。但到了React的世界,特别是用函数组件和Hooks,你得换个思路了。

在原来的Vue组件里,我们大概会这么写:

const likes = ref(0)
const hearts = ref([])
const container = ref(null)
const clickTime = ref(0)

四个变量,清晰明了。likes 记录总点赞数,hearts 数组存着每一个爱心动画的坐标和ID,container 用来拿DOM节点计算点击位置,clickTime 则是判断双击的关键计时器。

迁移到React 19,我们得用 useStateuseRef 这两个Hook来对应。这里就出现了第一个关键决策点:哪些状态用 useState,哪些用 useRef 原则其实很简单:需要触发组件重新渲染的数据,用 useState;不需要触发渲染、只是用来存个“快照”或者引用DOM的,用 useRef

所以,对应关系就出来了:

  • likeshearts 直接影响UI(一个要显示数字,一个要渲染一堆爱心),所以用 useState
  • containerRefclickTimeRef 不直接导致UI变化(一个只是DOM引用,一个只是内部计时),所以用 useRef
const [likes, setLikes] = useState<number>(0)
const [hearts, setHearts] = useState<Heart[]>([])
const containerRef = useRef<HTMLDivElement>(null)
const clickTimeRef = useRef<number>(0)

我刚开始用React的时候,老喜欢把所有东西都塞进 useState,结果就是组件莫名其妙地频繁重渲染,性能卡顿。后来才明白,useRef 就像是组件的一个“私人抽屉”,里面放的东西变了,不会惊动React去重新画页面,特别适合放那些“幕后工作者”。

比如这个 clickTimeRef,它只在上一次点击和当前点击之间做减法,判断时间差是否小于800毫秒。这个计算过程跟UI一毛钱关系都没有,如果用 useState,每次点击都要触发两次渲染(一次更新clickTime,一次可能更新hearts),纯属浪费。用 useRef 就安静多了,组件该干嘛干嘛,完全不受影响。

2. 事件处理:从模板语法到函数式回调

Vue里处理点击事件,我们通常在模板里写个 @click="handleClick" 就完事了,事件对象 $event 会自动传进去。但在React的JSX里,事件处理是直接以函数的形式绑定的,并且有更严格的类型安全。

在React里,我们这样写:

<div ... onClick={handleClick}>

注意,这里传的是函数名 handleClick,而不是字符串 "handleClick",也不是函数调用 handleClick()。这是一个新手常踩的坑,如果加了括号,函数会在渲染时立即执行,而不是在点击时执行。

事件处理函数本身,也从Vue的选项式写法,变成了一个纯粹的JavaScript/TypeScript函数:

const handleClick = (e: React.MouseEvent) => {
  const now = Date.now()
  if (clickTimeRef.current === 0) {
    clickTimeRef.current = now
  } else {
    if (now - clickTimeRef.current < 800) {
      createHeart(e)
      clickTimeRef.current = 0
    } else {
      clickTimeRef.current = now
    }
  }
}

这里有个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值