React中如何点击兄弟组件元素滚动到目标组件元素?
React字母导航滚动到对应国家列表项
我是ReactJS新手,开发了一个ReactJS/Vite应用,会获取并按字母顺序列出欧洲国家。我添加了一个包含可点击字母的侧边导航,希望点击某个字母时,应用能滚动到以该字母开头的第一个国家。目前我的SideNav和ListCountries组件是父组件App的兄弟组件。
App组件代码
function App() { useEffect(() => { fetch('https://restcountries.com/v3.1/region/europe') .then((data) => data.json()) .then((data) => { setCountries(data); //do stuff.. } }); }, []); return ( <div className='App'> <div className='row h-25 w-100 ps-5'> {/* 展示字母的组件 */} {alphabet && alphabet.map((letter) => ( <CardAlphabet letter={alphabet} /> ) )} </div> <ul> {/* 按字母顺序展示国家的组件 */} {countries && countries.map((country, id) => ( key={id} <Country id={id} name={country.name.common} /> ) )} </ul> </div> ); }
CardAlphabet组件代码
export default function CardAlphabet(props) { return ( <div className='col-lg-2'> <span className='some-classes'> {props.letter} </span> </div> ); }
Country组件代码
import { useEffect, useRef } from 'react'; import { useInView } from 'framer-motion'; import { useCountryStore } from './Cards/Store'; import classNames from 'classnames'; export const Country = (props) => { const ref = useRef(); const isInView = useInView(ref, { margin: '-50% 0px -50% 0px' }); const id = props.id; const countryStore = useCountryStore(); const firstLetter = props.dataFirstLetter; useEffect(() => { if (isInView) { countryStore.setInViewCountry(id); } if (!isInView && countryStore.inViewCountry === id) { countryStore.setInViewCountry(null); } }, [isInView, id]); // HandleClick用于点击国家时滚动到该元素,与当前问题无关 const handleClick = () => { ref.current?.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center', }); }; return ( <li onClick={handleClick} ref={ref} datafirstletter={firstLetter} className={classNames( 'some-classes' + props.id, isInView ? 'text-active' : '' )}> <p className={classNames(isInView ? 'text-active' : '')}>{props.name}</p> </li> ); };
我尝试给每个国家元素添加了带有其首字母的data属性,但不知道如何从兄弟组件访问该属性,以及如何滚动到指定data属性的元素,希望得到解决思路。
解决方法
我解决了这个问题!具体实现步骤如下:
- 推导每个国家名称的首字母,传递为规范的
data-first-letter属性给Country组件:
export const Country = (props) => { // 从国家名称提取首字母并转大写 const firstLetter = props.name.charAt(0).toUpperCase(); return ( <li data-first-letter={firstLetter} className="some-classes"> <p>{props.name}</p> </li> ); };
- 在App组件中定义滚动函数,通过点击事件传递给CardAlphabet组件:
function App() { function scrollToFirstLetter(targetLetter) { const targetElement = document.querySelector(`[data-first-letter='${targetLetter}']`); if (targetElement) { targetElement.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center', }); } } // ... 其他逻辑(获取国家数据等) return( <div className='App'> <div className='row h-25 w-100 ps-5'> {alphabet && alphabet.map((letter) => ( <CardAlphabet key={letter} onClick={() => scrollToFirstLetter(letter)} letter={letter} presentLetter={presentSubNames} /> ) )} </div> {/* 国家列表渲染部分 */} </div> ) }
通过上述方式,就能获取导航中被点击的字母,定位到对应首字母的第一个国家元素,并平滑滚动到该位置。
内容的提问来源于stack exchange,提问作者Bagdadi7
相关产品推荐
相关产品推荐

