如何将实现骰子滚动功能的jQuery代码转换为React可用代码?
jQuery 骰子逻辑迁移 React 实现方案
React 开发核心是状态驱动视图,不要手动操作DOM,你原来的CSS可以100%复用,只需要把DOM操作逻辑替换成React状态管理即可,以下是可直接使用的函数组件实现(基于React 16.8+ Hooks语法,是目前主流写法):
逻辑对应关系
- 原jQuery中手动存的临时变量(定时器ID、上一次掷出的点数)用
useRef存储,这类值变化不需要触发界面重渲染 - 原代码里手动给元素加/删class、改
data-face属性的操作,全部通过state变化自动驱动渲染,不需要手动查找DOM修改 - 原代码里给元素绑定的点击事件,直接写在对应JSX标签的
onClick属性上,不需要提前选择DOM绑定监听 - 组件卸载时必须清除未执行的定时器,避免内存泄漏
完整实现代码
import { useState, useRef, useEffect } from 'react'; const DiceRoller = () => { // 固定配置项 const SIDES = 20; const INITIAL_SIDE = 1; const ANIMATION_DURATION = 3000; // 视图相关状态,变化会自动触发界面更新 const [currentFace, setCurrentFace] = useState(INITIAL_SIDE); const [isRolling, setIsRolling] = useState(false); const [activeNav, setActiveNav] = useState(INITIAL_SIDE); // 非视图状态,变化不触发重渲染 const lastFaceRef = useRef(null); const timerRef = useRef(null); // 组件卸载时清理定时器 useEffect(() => { return () => { if (timerRef.current) clearTimeout(timerRef.current); } }, []); // 生成不和上一次重复的随机点数 const getRandomFace = () => { let face = Math.floor(Math.random() * SIDES) + INITIAL_SIDE; if (face === lastFaceRef.current) face = getRandomFace(); lastFaceRef.current = face; return face; }; // 重置骰子状态 const resetDice = () => { if (timerRef.current) clearTimeout(timerRef.current); setIsRolling(false); setCurrentFace(null); }; // 滚动到指定点数 const rollTo = (face) => { if (timerRef.current) clearTimeout(timerRef.current); const target = Number(face); setActiveNav(target); setCurrentFace(target); }; // 点击侧边点数导航 const handleNavClick = (e, face) => { e.preventDefault(); resetDice(); rollTo(face); }; // 触发随机掷骰子 const handleRandomRoll = (e) => { e.preventDefault(); if (timerRef.current) clearTimeout(timerRef.current); setIsRolling(true); timerRef.current = setTimeout(() => { setIsRolling(false); rollTo(getRandomFace()); }, ANIMATION_DURATION); }; return ( <div className="dice-container"> {/* 点数选择导航,对应原代码ul>li>a结构 */} <ul> {Array.from({ length: SIDES }, (_, i) => i + INITIAL_SIDE).map(face => ( <li key={face}> <a href={`#${face}`} className={activeNav === face ? 'active' : ''} onClick={(e) => handleNavClick(e, face)} > {face} </a> </li> ))} </ul> {/* 骰子本体,最终渲染的class、data-face属性和原jQuery版本完全一致 */} <div className={`die ${isRolling ? 'rolling' : ''}`} data-face={currentFace} onClick={handleRandomRoll} > {/* 这里放你原来骰子各个面的DOM结构即可,不用修改 */} </div> {/* 随机掷骰按钮 */} <button className="randomize" onClick={handleRandomRoll}> 掷骰子 </button> </div> ); }; export default DiceRoller;
使用说明
- 你之前写的所有CSS样式、骰子内部的面结构完全不用调整,最终渲染出的DOM结构和jQuery版本完全一致,动画效果可以直接复用
- 事件回调里的
e.preventDefault()等价于原jQuery代码里的return false,用来阻止a标签的默认跳转行为 - 如果你的项目用的是类组件,逻辑完全一致,只需要把useState换成this.state、useRef换成类属性、useEffect换成componentWillUnmount即可。
内容的提问来源于stack exchange,提问作者Eric Wargin
相关产品推荐
相关产品推荐

