我有一个聊天小部件,每次向上滚动时都会拉出一系列消息。我现在面临的问题是消息加载时滑块固定在顶部。我希望它专注于前一个数组中的最后一个索引元素。我发现我可以通过传递索引来制作动态引用,但我还需要知道使用哪种滚动函数来实现这一点
handleScrollToElement(event) {
const tesNode = ReactDOM.findDOMNode(this.refs.test)
if (some_logic){
//scroll to testNode
}
}
render() {
return (
<div>
<div ref="test"></div>
</div>)
}
React 16.8 +,函数式组件
const ScrollDemo = () => {
const myRef = useRef(null)
const executeScroll = () => myRef.current.scrollIntoView()
// run this function from an event handler or an effect to execute scroll
return (
<>
<div ref={myRef}>Element to scroll to</div>
<button onClick={executeScroll}> Click to scroll </button>
</>
)
}
Click here for a full demo on StackBlits
React 16.3 +,类组件
class ReadyToScroll extends Component {
constructor(props) {
super(props)
this.myRef = React.createRef()
}
render() {
return <div ref={this.myRef}>Element to scroll to</div>
}
executeScroll = () => this.myRef.current.scrollIntoView()
// run this method to execute scrolling.
}
类组件 - Ref 回调
class ReadyToScroll extends Component {
render() {
return <div ref={ (ref) => this.myRef=ref }>Element to scroll to</div>
}
executeScroll = () => this.myRef.scrollIntoView()
// run this method to execute scrolling.
}
不要使用字符串引用。
字符串引用会损害性能,不可组合,并且即将淘汰(2018 年 8 月)。
字符串引用有一些问题,被认为是遗留问题,并且可能会在未来的某个版本中被删除。 [官方反应文档]
可选:平滑滚动动画
/* css */
html {
scroll-behavior: smooth;
}
将 ref 传递给孩子
我们希望 ref 附加到 dom 元素,而不是 react 组件。因此,当将它传递给子组件时,我们不能命名 prop ref。
const MyComponent = () => {
const myRef = useRef(null)
return <ChildComp refProp={myRef}></ChildComp>
}
然后将 ref 属性附加到 dom 元素。
const ChildComp = (props) => {
return <div ref={props.refProp} />
}
这对我有用
this.anyRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' })
编辑:我想根据评论对此进行扩展。
const scrollTo = (ref) => {
if (ref && ref.current /* + other conditions */) {
ref.current.scrollIntoView({ behavior: 'smooth', block: 'start' })
}
}
<div ref={scrollTo}>Item</div>
只需找到您已确定的元素的顶部位置 https://www.w3schools.com/Jsref/prop_element_offsettop.asp,然后通过 scrollTo
方法 https://www.w3schools.com/Jsref/met_win_scrollto.asp 滚动到该位置
像这样的东西应该工作:
handleScrollToElement(event) {
const tesNode = ReactDOM.findDOMNode(this.refs.test)
if (some_logic){
window.scrollTo(0, tesNode.offsetTop);
}
}
render() {
return (
<div>
<div ref="test"></div>
</div>)
}
更新:
由于 React v16.3 首选 React.createRef()
constructor(props) {
super(props);
this.myRef = React.createRef();
}
handleScrollToElement(event) {
if (<some_logic>){
window.scrollTo(0, this.myRef.current.offsetTop);
}
}
render() {
return (
<div>
<div ref={this.myRef}></div>
</div>)
}
ReactDOM.findDomNode()
是更好的做法 - 因为 React 会重新渲染组件,所以在您调用函数时,您只需通过其 ID 获取的 div 可能不存在
findDOMNode
。在大多数情况下,您可以将 ref 附加到 DOM 节点并完全避免使用 findDOMNode
。
this.myRef.current.scrollIntoView()
而不是 window.scrollTo(0, this.myRef)
。
我有一个简单的场景,当用户单击 Material UI Navbar 中的菜单项时,我想将它们向下滚动到页面上的部分。我可以使用 refs 并将它们穿过所有组件,但我讨厌将 props 穿过多个组件,因为这会使代码变得脆弱。
我刚刚在我的 react 组件中使用了 vanilla JS,结果它工作得很好。在我想要滚动到的元素上放置一个 ID,在我的标题组件中我只是这样做了。
const scroll = () => {
const section = document.querySelector( '#contact-us' );
section.scrollIntoView( { behavior: 'smooth', block: 'start' } );
};
您现在可以使用来自 react hook API 的 useRef
https://reactjs.org/docs/hooks-reference.html#useref
宣言
let myRef = useRef()
零件
<div ref={myRef}>My Component</div>
利用
window.scrollTo({ behavior: 'smooth', top: myRef.current.offsetTop })
console.log
看到它正在执行您的 window.scrollTo
语句(针对我的情况进行了调整),但它没有滚动。这可能与我使用 React Bootstrap 模式有关吗?
2019 年 7 月 - 专用挂钩/功能
专用的钩子/函数可以隐藏实现细节,并为您的组件提供简单的 API。
React 16.8 + 功能组件
const useScroll = () => {
const elRef = useRef(null);
const executeScroll = () => elRef.current.scrollIntoView();
return [executeScroll, elRef];
};
在任何功能组件中使用它。
const ScrollDemo = () => {
const [executeScroll, elRef] = useScroll()
useEffect(executeScroll, []) // Runs after component mounts
return <div ref={elRef}>Element to scroll to</div>
}
React 16.3 + 类组件
const utilizeScroll = () => {
const elRef = React.createRef();
const executeScroll = () => elRef.current.scrollIntoView();
return { executeScroll, elRef };
};
在任何类组件中使用它。
class ScrollDemo extends Component {
constructor(props) {
super(props);
this.elScroll = utilizeScroll();
}
componentDidMount() {
this.elScroll.executeScroll();
}
render(){
return <div ref={this.elScroll.elRef}>Element to scroll to</div>
}
}
useScroll
的返回类型声明为 [() => void, RefObject<HTMLInputElement>]
。然后您可以毫无问题地调用 executeScroll()
最好的方法是使用 element.scrollIntoView({ behavior: 'smooth' })
。这会通过漂亮的动画将元素滚动到视图中。
当你将它与 React 的 useRef()
结合使用时,可以通过以下方式完成。
import React, { useRef } from 'react'
const Article = () => {
const titleRef = useRef()
function handleBackClick() {
titleRef.current.scrollIntoView({ behavior: 'smooth' })
}
return (
<article>
<h1 ref={titleRef}>
A React article for Latin readers
</h1>
// Rest of the article's content...
<button onClick={handleBackClick}>
Back to the top
</button>
</article>
)
}
当你想滚动到一个 React 组件时,你需要将 ref 转发给渲染的元素。 This article will dive deeper into the problem。
(ref) => window.scrollTo(0, ref.current.offsetTop)
,但后来只从顶部得到了一个小的偏移量而没有到达目标。我相信这是因为裁判的位置是在开始时计算出来的,然后没有更新。您的建议解决了我的问题,而接受的答案却没有。
您还可以使用 scrollIntoView
方法滚动到给定元素。
handleScrollToElement(event) {
const tesNode = ReactDOM.findDOMNode(this.refs.test)
if (some_logic){
tesNode.scrollIntoView();
}
}
render() {
return (
<div>
<div ref="test"></div>
</div>)
}
我可能迟到了,但我试图以正确的方式对我的项目实施动态参考,直到知道我发现的所有答案都不能满足我的喜好,所以我想出了一个我认为是的解决方案简单并使用本机和推荐的反应方式来创建参考。
有时您会发现编写文档的方式假设您拥有已知数量的视图,并且在大多数情况下这个数字是未知的,因此您需要一种方法来解决这种情况下的问题,为您需要的未知数量的视图创建动态引用在课堂上展示
所以我能想到并完美工作的最简单的解决方案是执行以下操作
class YourClass extends component {
state={
foo:"bar",
dynamicViews:[],
myData:[] //get some data from the web
}
inputRef = React.createRef()
componentDidMount(){
this.createViews()
}
createViews = ()=>{
const trs=[]
for (let i = 1; i < this.state.myData.lenght; i++) {
let ref =`myrefRow ${i}`
this[ref]= React.createRef()
const row = (
<tr ref={this[ref]}>
<td>
`myRow ${i}`
</td>
</tr>
)
trs.push(row)
}
this.setState({dynamicViews:trs})
}
clickHandler = ()=>{
//const scrollToView = this.inputRef.current.value
//That to select the value of the inputbox bt for demostrate the //example
value=`myrefRow ${30}`
this[value].current.scrollIntoView({ behavior: "smooth", block: "start" });
}
render(){
return(
<div style={{display:"flex", flexDirection:"column"}}>
<Button onClick={this.clickHandler}> Search</Button>
<input ref={this.inputRef}/>
<table>
<tbody>
{this.state.dynamicViews}
<tbody>
<table>
</div>
)
}
}
export default YourClass
这样滚动将转到您要查找的任何行..
欢呼,希望它可以帮助别人
你可以这样尝试:
handleScrollToElement = e => {
const elementTop = this.gate.offsetTop;
window.scrollTo(0, elementTop);
};
render(){
return(
<h2 ref={elem => (this.gate = elem)}>Payment gate</h2>
)}
这个解决方案在 ReactJS 中适用于我
在 header.js 中
function scrollToTestDiv(){
const divElement = document.getElementById('test');
divElement.scrollIntoView({ behavior: 'smooth' });
}
<a class="nav-link" onClick={scrollToTestDiv}> Click here! </a>
在 index.html 中
<div id="test"></div>
您可以使用类似 componentDidUpdate
componentDidUpdate() {
var elem = testNode //your ref to the element say testNode in your case;
elem.scrollTop = elem.scrollHeight;
};
这是您可以用来解决此问题的类组件代码片段:
这种方法使用了 ref 并且还平滑滚动到目标 ref
import React, { Component } from 'react'
export default class Untitled extends Component {
constructor(props) {
super(props)
this.howItWorks = React.createRef()
}
scrollTohowItWorks = () => window.scroll({
top: this.howItWorks.current.offsetTop,
left: 0,
behavior: 'smooth'
});
render() {
return (
<div>
<button onClick={() => this.scrollTohowItWorks()}>How it works</button>
<hr/>
<div className="content" ref={this.howItWorks}>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nesciunt placeat magnam accusantium aliquid tenetur aspernatur nobis molestias quam. Magnam libero expedita aspernatur commodi quam provident obcaecati ratione asperiores, exercitationem voluptatum!
</div>
</div>
)
}
}
如果有人在使用 Typescript,这里是 Ben Carp 的回答:
import { RefObject, useRef } from 'react';
export const useScroll = <T extends HTMLElement>(
options?: boolean | ScrollIntoViewOptions
): [() => void, RefObject<T>] => {
const elRef = useRef<T>(null);
const executeScroll = (): void => {
if (elRef.current) {
elRef.current.scrollIntoView(options);
}
};
return [executeScroll, elRef];
};
ScrollIntoViewOptions
的定义和示例用法。
按着这些次序:
1)安装:
npm install react-scroll-to --save
2)导入包:
import { ScrollTo } from "react-scroll-to";
3) 用法:
class doc extends Component {
render() {
return(
<ScrollTo>
{({ scroll }) => (
<a onClick={() => scroll({ x: 20, y: 500, , smooth: true })}>Scroll to Bottom</a>
)}
</ScrollTo>
)
}
}
react-scroll-to
非常有用。
我在 onclick 函数中使用它来平滑滚动到其 id 为“step2Div”的 div。
let offset = 100;
window.scrollTo({
behavior: "smooth",
top:
document.getElementById("step2Div").getBoundingClientRect().top -
document.body.getBoundingClientRect().top -
offset
});
在阅读了许多论坛后,发现了一个非常简单的解决方案。
我使用 redux 形式。 Urgo 映射 redux-from fieldToClass。出现错误时,我会导航到 syncErrors 列表中的第一个错误。
没有参考和第三方模块。只是简单的 querySelector
& scrollIntoView
handleToScroll = (field) => {
const fieldToClass = {
'vehicleIdentifier': 'VehicleIdentifier',
'locationTags': 'LocationTags',
'photos': 'dropzoneContainer',
'description': 'DescriptionInput',
'clientId': 'clientId',
'driverLanguage': 'driverLanguage',
'deliveryName': 'deliveryName',
'deliveryPhone': 'deliveryPhone',
"deliveryEmail": 'deliveryEmail',
"pickupAndReturn": "PickupAndReturn",
"payInCash": "payInCash",
}
document?.querySelector(`.${fieldToClasses[field]}`)
.scrollIntoView({ behavior: "smooth" })
}
为了自动滚动到特定元素,首先需要使用 document.getElementById 选择元素,然后我们需要使用 scrollIntoView() 进行滚动。请参考以下代码。
scrollToElement= async ()=>{
document.getElementById('id001').scrollIntoView();
}
上述方法对我有用。
如果您想在页面加载时执行此操作,您可以使用 useLayoutEffect 和 useRef。
import React, { useRef, useLayoutEffect } from 'react'
const ScrollDemo = () => {
const myRef = useRef(null)
useLayoutEffect(() => {
window.scrollTo({
behavior: "smooth",
top: myRef.current.offsetTop,
});
}, [myRef.current]);
return (
<>
<div ref={myRef}>I wanna be seen</div>
</>
)
}
您可以将 useRef
与 scrollIntoView
一起使用。
对要滚动到的元素使用 useRef:这里我想滚动到 PieceTabs 元素,这就是为什么我用 Box(div) 包装它,这样我就可以访问 dom 元素
您可能熟悉 refs 主要是作为访问 DOM 的一种方式。如果你将一个 ref 对象传递给 React,只要该节点发生变化,React 就会将其 .current 属性设置为相应的 DOM 节点。查看文档
...
const tabsRef = useRef()
...
<Box ref={tabsRef}>
<PieceTabs piece={piece} value={value} handleChange={handleChange} />
</Box>
...
创建一个处理此滚动的函数:
const handleSeeCompleteList = () => {
const tabs = tabsRef.current
if (tabs) {
tabs.scrollIntoView({
behavior: 'smooth',
block: 'start',
})
}
}
单击滚动到目标后,在所需元素上调用此函数:
<Typography
variant="body2"
sx={{
color: "#007BFF",
cursor: "pointer",
fontWeight: 500,
}}
onClick={(e) => {
handleChange(e, 2);
handleSeeCompleteList(); // here we go
}}
>
Voir toute la liste
</Typography>;
https://i.stack.imgur.com/OrjAh.gif
<div id="componentToScrollTo"><div>
<a href='#componentToScrollTo'>click me to scroll to this</a>
这就是你所需要的。
什么对我有用:
class MyComponent extends Component {
constructor(props) {
super(props);
this.myRef = React.createRef(); // Create a ref
}
// Scroll to ref function
scrollToMyRef = () => {
window.scrollTo({
top:this.myRef.offsetTop,
// behavior: "smooth" // optional
});
};
// On component mount, scroll to ref
componentDidMount() {
this.scrollToMyRef();
}
// Render method. Note, that `div` element got `ref`.
render() {
return (
<div ref={this.myRef}>My component</div>
)
}
}
请注意,我无法让这些解决方案在 Material UI 组件上运行。看起来他们没有 current
属性。
我只是在我的组件中添加了一个空的 div
并在其上设置了 ref 属性。
对于阅读本文但对上述解决方案不太满意或只想要一个简单的嵌入式解决方案的其他人,这个包对我有用:https://www.npmjs.com/package/react-anchor-link-smooth-scroll。快乐黑客!
这是我的解决方案:
我在主 div 中放置了一个不可见的 div 并将其位置设为绝对。然后将顶部值设置为 -(header height) 并在此 div 上设置 ref。或者你可以用 children 方法来反应那个 div。
到目前为止效果很好!
<div className="position-relative">
<div style={{position:"absolute", top:"-80px", opacity:0, pointerEvents:'none'}} ref={ref}></div>
也许有人会遇到像我这样的情况
https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node
如何测量 DOM 节点?测量 DOM 节点的位置或大小的一种基本方法是使用回调 ref。每当 ref 附加到不同的节点时,React 都会调用该回调。这是一个小演示:
function MeasureExample() {
const [height, setHeight] = useState(0);
const measuredRef = useCallback(node => {
if (node !== null) {
setHeight(node.getBoundingClientRect().height);// you can scroll in this line
}
}, []);
return (
<>
<h1 ref={measuredRef}>Hello, world</h1>
<h2>The above header is {Math.round(height)}px tall</h2>
</>
);
}
在这个例子中我们没有选择 useRef,因为一个对象 ref 没有通知我们当前 ref 值的变化。使用回调 ref 可确保即使子组件稍后显示测量节点(例如响应单击),我们仍会在父组件中收到有关它的通知并可以更新测量值。
请注意,我们将 [] 作为依赖数组传递给 useCallback。这确保了我们的 ref 回调在重新渲染之间不会改变,因此 React 不会不必要地调用它。
在这个例子中,回调 ref 只会在组件安装和卸载时被调用,因为渲染的组件在任何重新渲染过程中都保持存在。如果您想在组件调整大小时收到通知,您可能需要使用 ResizeObserver 或基于它构建的第三方 Hook。
<div onScrollCapture={() => this._onScrollEvent()}></div>
_onScrollEvent = (e)=>{
const top = e.nativeEvent.target.scrollTop;
console.log(top);
}
这是我发现为我工作的最简单的方法。只需使用普通的 javascript 语法,不需要太多包
const scrollTohowItWorks = () => window.scroll({
top: 2000,
left: 0,
behavior: 'smooth'
});
<NavLink onClick={scrollTohowItWorks} style={({ isActive }) => isActive? {color: '#e26702', fontWeight:'bold'}: { color: '#0651b3'}} to=''>Support</NavLink>
不定期副业成功案例分享
window.scrollTo(0, offsetTop)
是更好的选择,在当前浏览器中具有更好的支持