React.js中如何使用ref修改循环渲染的多个元素的样式?
问题根因
你为循环渲染的所有div绑定了同一个barRef引用,单值ref在循环赋值过程中会被不断覆盖,最终只会保留最后一个渲染DOM元素的引用,这就是只能修改最后一个div高度的原因。同时你代码里的Math.random(10)写法有误,Math.random()不接收参数,默认返回0~1之间的随机数。
解决方案1:数据驱动渲染(React推荐写法)
React推荐用状态控制视图,不要直接操作DOM。我们可以把所有柱子的高度存入状态数组,点击随机按钮时更新整个数组即可自动同步视图:
import React, { useState } from 'react' import "../styling/Sorting.css"; import Slider from '@material-ui/core/Slider'; function Sorting() { // 滑块值:柱子数量 const [value, setValue] = useState(0); // 存储所有柱子的高度 const [heights, setHeights] = useState([]); const changeValue = (event, newValue) => { setValue(newValue) // 滑块变化时初始化新柱子的默认高度,可自定义 setHeights(prev => { const newHeights = [...prev] // 新增柱子时补充默认高度 while(newHeights.length < newValue) { newHeights.push(Math.floor(Math.random() * 500)) } // 减少柱子时截断数组 return newHeights.slice(0, newValue) }) } function randomHeight(){ // 生成对应数量的随机高度数组 const newHeights = Array.from({length: value}, () => Math.floor(Math.random() * 500)) setHeights(newHeights) } return ( <div className="container"> <nav> <div className="slider"> <Slider value={value} onChange={changeValue} max={30} valueLabelDisplay="on"/> </div> <div className="random_height"> <button onClick={randomHeight}>random</button> </div> </nav> <div className="bars"> {/* 直接用状态里的高度渲染,不需要操作DOM */} {heights.map((height, i) => ( <div className="bar" key={i} style={{height: `${height}px`}} ></div> ))} </div> </div> ) } export default Sorting
解决方案2:使用Ref数组(适合需要直接操作DOM的场景)
如果你的业务场景需要直接操作DOM元素,可以用数组存储所有柱子的ref:
import React, { useState, useRef } from 'react' import "../styling/Sorting.css"; import Slider from '@material-ui/core/Slider'; function Sorting() { const [value, setValue] = useState(0); const changeValue = (event, newValue) => { setValue(newValue) } // 声明ref数组存储所有柱子的DOM引用 const barRefs = useRef([]) function randomHeight(){ // 遍历所有ref设置随机高度 barRefs.current.forEach(bar => { if(bar) { const randomH = Math.floor(Math.random() * 500) bar.style.height = `${randomH}px` } }) } return ( <div className="container"> <nav> <div className="slider"> <Slider value={value} onChange={changeValue} max={30} valueLabelDisplay="on"/> </div> <div className="random_height"> <button onClick={randomHeight}>random</button> </div> </nav> <div className="bars"> {Array.from({ length: value }, (_, i) => ( <div className="bar" key={i} // 把每个DOM元素存入对应下标的ref位置 ref={el => barRefs.current[i] = el} ></div> ))} </div> </div> ) } export default Sorting
内容的提问来源于stack exchange,提问作者Saif Khadraoui
相关产品推荐
相关产品推荐

