提问人:Unnamed 提问时间:6/21/2023 最后编辑:Ahmed SbaiUnnamed 更新时间:6/26/2023 访问量:139
确定当前使用 react 和 Waypoint 支付的哪个部分
Determine which section is currently dispayed with react and Waypoint
问:
我有非常简单的react应用程序:
App.js:
render() {
return (
<BaseLayout />
);
}
基础布局:
import React, { useEffect, useState } from 'react';
import Navbar from "./Navbar";
import Section1 from "./section1/Section1";
import Section2 from "./section2/Section2";
import Section3 from "./section3/Section3";
import { Box, Grid } from "@mui/material";
import Fade from "react-awesome-reveal";
import { Waypoint } from 'react-waypoint';
我只是一次显示所有部分,然后用动画显示它们。一切都很好。但我也想突出显示当前显示的部分,并在滚动过程中相应地更改它(当前突出显示仅在单击期间发生)Fade
Navbar
return (
<Box className={darkMode ? Style.dark : Style.light}>
<Grid
container
display={"flex"}
flexDirection={"column"}
minHeight={"100vh"}
justifyContent={"space-between"}
>
<Grid item>
<Navbar darkMode={darkMode} handleClick={handleToggleDarkMode} />
</Grid>
<Grid item flexGrow={1} className={Style.firstContentRow}>
<Section1 />
</Grid>
<Grid item flexGrow={1}>
<Fade bottom triggerOnce={true} className={Style.secondContentRow}>
<Section2 />
</Fade>
</Grid>
<Grid item flexGrow={1} className={Style.firstContentRow}>
<Fade bottom triggerOnce={true}>
<Section3 />
</Fade>
</Grid>
<Waypoint
onEnter={({ previousPosition, currentPosition, event }) => {
// PreviousPosition:below
// CurrentPosition:inside
// The above fields just return either `below` or `inside` and *NOT* for each section.
console.log("PreviousPosition:" + previousPosition);
console.log("CurrentPosition:" + currentPosition);
// I see no usefull data here as well, did I miss something?
console.log("Event:" + event);
}}
/>
</Grid>
</Box>
);
为此,我认为我需要使用他的一些事件,这应该让我知道现在显示的是哪个特定部分,然后相应地更改特定导航栏按钮上的类名。但是,航点事件提供的信息看起来还不够。我找不到如何理解此时显示哪个特定部分。我错过了什么吗?此外,正如我所看到的,该事件不是针对每个部分触发的,并且只针对最后一个部分触发Waypoint
答:
要回答该问题,请执行以下操作:
<Waypoint/>
无助于实现你想要的东西,它不是用来的,它实际上是一个你可以放在你的 jsx 中的组件。
适用于所有可以滚动的容器,包括窗口。
当您滚动时,您可以将其视为一个点,一旦到达、离开或改变位置,就会触发相应的事件。
当您输入此点时,前一个位置始终在此处“下方”,因为您已经放在网格的末尾。
该对象对于您想要的内容也没有用,如果您选中,您将找到整个可滚动元素,而不是屏幕上最后显示的元素。<Waypoint/>
event
event.doccument
event - 触发回调的本机滚动事件。如果回调不是由于滚动而触发的,则可能会丢失。
所以通常使用
构建延迟加载内容、无限滚动、滚动间谍或在滚动时将元素停靠到视口等功能。
溶液:
您可以在每个部分之前使用三个,并在一个状态之前使用一个状态来指示哪个是最后一个航点(显示的部分的顺序):<Waypoint/>
const [currentSection, setCurrentSection] = useState(1);
然后创建一个钩子,每次更新时都要运行:useEffect
currentSection
useEffect(() => {
console.log("current section is updated and this is its order ", currentSection);
// now you have the number indicates of the current section you can manage how to make your nav bar react to that
}, [currentSection]);
JSX:
<Box>
<Waypoint
onEnter={() => {
setCurrentSection(1);
}}
/>
<Grid
container
display={"flex"}
flexDirection={"column"}
minHeight={"100vh"}
justifyContent={"space-between"}
>
<Grid
item
flexGrow={1}
style={{ height: "800px", background: "red" }}
>
<div>section 1</div>
</Grid>
<Waypoint
onEnter={() => {
setCurrentSection(2);
}}
/>
<Grid
item
flexGrow={1}
style={{ height: "800px", background: "white" }}
>
<div>section 2</div>
</Grid>
<Waypoint
onEnter={() => {
setCurrentSection(3);
}}
/>
<Grid
item
flexGrow={1}
style={{ height: "800px", background: "green" }}
>
<div>section 3</div>
</Grid>
</Grid>
</Box>
备选方案(不带航点):
我曾经使用滚动和引用的事件侦听器来管理它。
您希望为每个部分容器提供 a 和 an,以及指示当前屏幕上哪个部分的状态:ref
id
grid
const firstRef = useRef();
const secondRef = useRef();
const ThirdRef = useRef();
const [currentSection, setCurrentSection] = useState();
当组件挂载到第一部分并设置事件侦听器时:setCurrentSection
useEffect(() => {
setCurrentSection(firstRef.current);
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
每次滚动和更新状态时,该函数都会运行,但可能只有在获得新值时才会重新渲染组件:handleScroll
currentSection
currentSection
const handleScroll = () => {
const scrollPosition = window.scrollY || document.documentElement.scrollTop;
const windowHeight = window.innerHeight;
const sectionPositions = [
firstRef.current,
secondRef.current,
ThirdRef.current
];
const currentSection = sectionPositions.find(
(section) =>
scrollPosition >= section.offsetTop &&
scrollPosition < section.offsetTop + windowHeight
);
if (currentSection) {
setCurrentSection(currentSection);
}
};
最后,我们创建一个钩子,每次更新 的值时都会触发该钩子:useEffect
currentSection
useEffect(() => {
if (currentSection) {
console.log("current section is updated and this is the id of the current one: ", currentSection.id);
// now you have the id of the current section you can manage how to make your nav bar react to that
}
}, [currentSection]);
完整示例:
const Test = () => {
const firstRef = useRef();
const secondRef = useRef();
const ThirdRef = useRef();
const [currentSection, setCurrentSection] = useState();
const handleScroll = () => {
const scrollPosition = window.scrollY || document.documentElement.scrollTop;
const windowHeight = window.innerHeight;
const sectionPositions = [ firstRef.current, secondRef.current, ThirdRef.current ];
const currentSection = sectionPositions.find(
(section) =>
scrollPosition >= section.offsetTop && scrollPosition < section.offsetTop + windowHeight
);
if (currentSection) {
setCurrentSection(currentSection);
}
};
useEffect(() => {
setCurrentSection(firstRef.current);
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
useEffect(() => {
if (currentSection) {
console.log("current section is updated and this is the id of the current one: ", currentSection.id );
// now you have the id of the current section you can manage how to make your nav bar react to that
}
}, [currentSection]);
return (
<div className="App">
<Box>
<Grid
container
display={"flex"}
flexDirection={"column"}
minHeight={"100vh"}
justifyContent={"space-between"}
>
<Grid
id={1}
item
flexGrow={1}
style={{ height: "800px", background: "red" }}
ref={firstRef}
>
<div>section 1</div>
</Grid>
<Grid
id={2}
item
flexGrow={1}
style={{ height: "800px", background: "white" }}
ref={secondRef}
>
<div>section 2</div>
</Grid>
<Grid
id={3}
item
flexGrow={1}
style={{ height: "800px", background: "green" }}
ref={ThirdRef}
>
<div>section 3</div>
</Grid>
</Grid>
</Box>
</div>
);
};
评论
Cannot read properties of undefined (reading 'offsetTop')
Cannot read properties of undefined (reading 'offsetTop')
handleScroll
if(firstRef.current && secondRef.current && thirdRef.current)
评论