วิธีการเลื่อนไปที่องค์ประกอบ?


181

ฉันมีวิดเจ็ตการแชทที่ดึงลำดับของข้อความทุกครั้งที่เลื่อนขึ้น ปัญหาที่ฉันกำลังเผชิญอยู่ในขณะนี้คือตัวเลื่อนยังคงอยู่ที่ด้านบนเมื่อโหลดข้อความ ฉันต้องการให้มันมุ่งเน้นไปที่องค์ประกอบดัชนีสุดท้ายจากอาร์เรย์ก่อนหน้า ฉันคิดว่าฉันสามารถสร้างการอ้างอิงแบบไดนามิกโดยผ่านดัชนี แต่ฉันก็ต้องรู้ว่าฟังก์ชั่นการเลื่อนแบบใดที่จะใช้เพื่อให้บรรลุ

 handleScrollToElement(event) {
    const tesNode = ReactDOM.findDOMNode(this.refs.test)
    if (some_logic){
      //scroll to testNode      
    }
  }

  render() {

    return (
      <div>
        <div ref="test"></div>
      </div>)
  }

1
สำหรับโซลูชันแบบรวม: npmjs.com/package/react-scroll-to-component
tokland

คำตอบ:


301

ทำปฏิกิริยา 16.8 + องค์ประกอบการทำงาน

import React, { useRef } from 'react'

const scrollToRef = (ref) => window.scrollTo(0, ref.current.offsetTop)   
// General scroll to element function

const ScrollDemo = () => {

   const myRef = useRef(null)
   const executeScroll = () => scrollToRef(myRef)

   return (
      <> 
         <div ref={myRef}>I wanna be seen</div> 
         <button onClick={executeScroll}> Click to scroll </button> 
      </>
   )
}

คลิกที่นี่เพื่อดูตัวอย่างเต็มรูปแบบบน StackBlits

ทำปฏิกิริยา 16.3 +, ส่วนประกอบของคลาส

class ReadyToScroll extends Component {

    constructor(props) {
        super(props)
        this.myRef = React.createRef()  
    }

    render() {
        return <div ref={this.myRef}></div> 
    }  

    scrollToMyRef = () => window.scrollTo(0, this.myRef.current.offsetTop)   
    // run this method to execute scrolling. 

}

องค์ประกอบระดับ - โทรกลับ Ref

class ReadyToScroll extends Component {
    myRef=null
    // Optional

    render() {
        return <div ref={ (ref) => this.myRef=ref }></div>
    } 

    scrollToMyRef = () => window.scrollTo(0, this.myRef.offsetTop)
    // run this method to execute scrolling. 
}

อย่าใช้การอ้างอิงสตริง

การอ้างอิงสตริงเป็นอันตรายต่อประสิทธิภาพการทำงานไม่สามารถปรับแต่งได้และกำลังจะหมดไป (Aug 2018)

การอ้างอิงสตริงมีปัญหาบางอย่างถือเป็นมรดกและมีแนวโน้มที่จะถูกลบออกในการเผยแพร่ในอนาคต [เอกสารตอบโต้ทางการ]

resource1 resource2

ทางเลือก: Smoothe scroll animation

/* css */
html {
    scroll-behavior: smooth;
}

ผ่านการอ้างอิงถึงเด็ก

เราต้องการอ้างอิงที่จะแนบกับองค์ประกอบ dom ไม่ได้เป็นองค์ประกอบที่ตอบสนอง ดังนั้นเมื่อส่งมันไปยังส่วนย่อยเราไม่สามารถตั้งชื่อผู้อ้างอิงได้

const MyComponent = () => {
    const myRef = useRef(null)
    return <ChildComp refProp={myRef}></ChildComp>
} 

จากนั้นแนบเสาอ้างอิงไปยังองค์ประกอบ dom

const ChildComp = (props) => {
    return <div ref={props.refProp} />
}

5
window.scrollTo(0, offsetTop)เป็นตัวเลือกที่ดีกว่าพร้อมรองรับเบราว์เซอร์ปัจจุบันที่ดีกว่า
MoMo

1
ตรวจสอบให้แน่ใจว่าคุณมีตัวอย่างที่สม่ำเสมอ เราเริ่มจาก myRef ไปกับ domRef และลงท้ายด้วย tesNode? นั่นค่อนข้างสับสน
Louis Lecocq

4
ชัดเจนหลังจากความจริง แต่เป็นสิ่งสำคัญที่จะกล่าวถึงว่าใช้งานได้เฉพาะกับองค์ประกอบ DOM พื้นเมืองและไม่เพียง แต่องค์ประกอบใด ๆ ที่ทำปฏิกิริยา
jpunk11

1
@ jpunk11 ฉันเพิ่งอัปเดตคำตอบของฉัน คำตอบที่ปรับปรุงแล้วอธิบายวิธีเลื่อนไปยังองค์ประกอบ dom ซึ่งอยู่ในองค์ประกอบระดับลูก
Ben Carp

2
@SimonFranzen ลองดูคำตอบที่อัปเดตของฉัน - TLDR - กรณีส่วนประกอบระดับ เมื่อ scrollToMyRef เรียกว่ามันจะเลื่อนไปที่เด็กที่คุณแนบอ้างอิง คุณสามารถส่งเมธอดไปยังคอมโพเนนต์ชายน์ที่แตกต่างกันและทริกเกอร์มันจากที่นั่น
Ben Carp

55

สิ่งนี้ใช้ได้สำหรับฉัน

this.anyRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' })

แก้ไข:ฉันต้องการขยายบนพื้นฐานของความคิดเห็น

const scrollTo = (ref) => {
  if (ref /* + other conditions */) {
    ref.scrollIntoView({ behavior: 'smooth', block: 'start' })
  }
}

<div ref={scrollTo}>Item</div>

1
สถานที่ที่จะวางนี้
su_sundariya

ในวิธีวงจรชีวิตหรือ
คอนสตรั

1
ทำงานเหมือนจับใจ ไม่มีข้อใดที่ใช้งานไม่ได้สำหรับฉันคำตอบนี้ควรได้รับการยอมรับ!
ชิน

1
ทำงานให้ฉันได้เพียงแค่ทราบว่า 'เริ่มต้น' เป็นค่าเริ่มต้นของพารามิเตอร์ 'บล็อก'
Liron Lavi

สิ่งนี้ใช้ได้กับฉันเมื่อ @Ben Carp ไม่ตอบ
Jason Masters

37

เพียงค้นหาตำแหน่งสูงสุดขององค์ประกอบที่คุณได้กำหนดไว้แล้ว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>)
}

UPDATE:

ตั้งแต่React v16.3React.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>)
}

2
นี่คือคำตอบที่ดีกว่า การใช้ReactDOM.findDomNode()เป็นแนวปฏิบัติที่ดีกว่า - เนื่องจาก React re-render component ส่วนประกอบที่คุณได้รับจาก ID อาจไม่มีอยู่ตามเวลาที่คุณเรียกใช้ฟังก์ชัน
Good Idea

4
findDOMNodeตามเอกสารอย่างเป็นทางการคุณควรพยายามที่จะหลีกเลี่ยงการใช้ ในกรณีส่วนใหญ่คุณสามารถแนบ ref ไปยังโหนด DOM และหลีกเลี่ยงการใช้findDOMNodeเลย
Facyo Kouch

1
โปรดทราบว่าการใช้ this.refs โดยการแมปสตริงจะถูกคัดค้านดู: stackoverflow.com/questions/43873511/ …
Himmet Avsar

1
หมายเหตุ: ผมใช้แทนthis.myRef.current.scrollIntoView() window.scrollTo(0, this.myRef)
Babbz77

14

การใช้ findDOMNode จะถูกคัดค้านในที่สุด

วิธีที่ต้องการคือใช้การอ้างอิงกลับ

github eslint


3
โปรดรวมส่วนที่เกี่ยวข้องของเนื้อหาที่เชื่อมโยงดังนั้นในกรณีที่คำตอบของคุณถูกลบออกจะไม่ไร้ประโยชน์
totymedli

12

ตอนนี้คุณสามารถใช้useRefจาก react hook API

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คำสั่งของคุณ(ปรับสำหรับกรณีของฉัน) แต่ยังไม่เลื่อน อาจเกี่ยวข้องกับความจริงที่ว่าฉันกำลังใช้ Modact Bootstrap Modal หรือไม่?
robertwerner_sf

9

นอกจากนี้คุณยังสามารถใช้scrollIntoViewวิธีการเลื่อนไปยังองค์ประกอบที่กำหนด

handleScrollToElement(event) {
const tesNode = ReactDOM.findDOMNode(this.refs.test)
 if (some_logic){
  tesNode.scrollIntoView();
  }
 }

 render() {
  return (
   <div>
     <div ref="test"></div>
   </div>)
}

9

ฉันอาจไปงานปาร์ตี้สาย แต่ฉันพยายามที่จะใช้การอ้างอิงแบบไดนามิกกับโครงการของฉันในวิธีที่เหมาะสมและคำตอบทั้งหมดที่ฉันพบจนกระทั่งรู้ว่าไม่เงียบสงบพอใจกับความชอบของฉันดังนั้นฉันจึงคิดวิธีแก้ปัญหาที่ฉันคิดว่าเป็น ง่ายและใช้วิธีการตอบสนองดั้งเดิมและแนะนำเพื่อสร้างการอ้างอิง

บางครั้งคุณพบว่าวิธีเขียนเอกสารถือว่าคุณมีจำนวนมุมมองที่เป็นที่รู้จักและในกรณีส่วนใหญ่จำนวนนี้ไม่เป็นที่รู้จักดังนั้นคุณต้องมีวิธีในการแก้ปัญหาในกรณีนี้ให้สร้างการอ้างอิงแบบไดนามิกตามจำนวนมุมมองที่คุณไม่ต้องการ เพื่อแสดงในชั้นเรียน

ดังนั้นทางออกที่ง่ายที่สุดที่ฉันสามารถคิดและทำงานได้อย่างไร้ที่ติคือทำดังต่อไปนี้

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

ทางนั้นการเลื่อนจะไปแถวใดก็ตามที่คุณกำลังมองหา ..

ไชโยและหวังว่ามันจะช่วยให้ผู้อื่น


8

ก.ค. 2019 - เบ็ด / ฟังก์ชั่นเฉพาะ

เบ็ด / ฟังก์ชั่นเฉพาะสามารถซ่อนรายละเอียดการติดตั้งและจัดเตรียม API อย่างง่ายสำหรับส่วนประกอบของคุณ

ทำปฏิกิริยา 16.8 + องค์ประกอบการทำงาน

const useScroll = () => {
  const htmlElRef = useRef(null)
  const executeScroll = () => window.scrollTo(0, htmlElRef.current.offsetTop)

  return [executeScroll, htmlElRef]
}

ใช้ในองค์ประกอบการทำงานใด ๆ

const ScrollDemo = () => {
    const [executeScroll, htmlElRef] = useScroll()
    useEffect(executeScroll, []) // Runs after component mounts

    return <div ref={htmlElRef}>Show me</div> 
}

การสาธิตเต็มรูปแบบ

ทำปฏิกิริยาส่วนประกอบคลาส 16.3 +

const utilizeScroll = () => {
  const htmlElRef = React.createRef()
  const executeScroll = () => window.scrollTo(0, htmlElRef.current.offsetTop)

  return {executeScroll, htmlElRef}
}

ใช้ในองค์ประกอบระดับใด ๆ

class ScrollDemo extends Component {
  constructor(){
    this.elScroll = utilizeScroll()
  }

  componentDidMount(){
    this.elScroll.executeScroll()
  }

  render(){
    return <div ref={this.elScroll.htmlElRef}>Show me</div> 
  }
} 

การสาธิตเต็มรูปแบบ


7

คุณสามารถลองด้วยวิธีนี้:

 handleScrollToElement = e => {
    const elementTop = this.gate.offsetTop;
    window.scrollTo(0, elementTop);
 };

 render(){
  return(
      <h2 ref={elem => (this.gate = elem)}>Payment gate</h2>
 )}

วิธีแก้ปัญหาที่ดีแม้ว่าคุณอาจต้องการ e.offsetTop แทน this.gate.offsetTop แล้วส่งผ่านสิ่งนี้ gate ไปยังฟังก์ชัน
KingOfHypocrites

5

คุณสามารถใช้สิ่งที่ชอบ componentDidUpdate

componentDidUpdate() {
  var elem = testNode //your ref to the element say testNode in your case; 
  elem.scrollTop = elem.scrollHeight;
};

3
ฉันคิดว่าการใช้องค์ประกอบรหัสไม่ได้เป็นที่ต้องการในการตอบสนอง มันแบ่งแนวคิดโดมเสมือน
iamsaksham

การใช้วิธีวงจรชีวิตเป็นวิธีที่จะไปไกลเท่าที่ / WHERE เพื่อเรียกใช้รหัส แต่อาจต้องการใช้วิธีการอื่น ๆ ที่คุณเห็นในคำตอบนี้สำหรับรหัสจริง
Dameo

3

ฉันมีสถานการณ์ง่าย ๆ เมื่อผู้ใช้คลิกที่รายการเมนูใน Navbar Material UI ของฉันฉันต้องการเลื่อนลงไปที่ส่วนบนหน้า ฉันสามารถใช้ refs และเธรดพวกเขาผ่านส่วนประกอบทั้งหมด แต่ฉันเกลียดการทำเกลียว props ประกอบฉากหลาย ๆ องค์ประกอบเพราะมันทำให้โค้ดมีความเปราะบาง

ฉันเพิ่งใช้วานิลลา JS ในองค์ประกอบการตอบสนองของฉันกลับกลายเป็นว่าใช้ได้ดี วาง ID บนองค์ประกอบที่ฉันต้องการเลื่อนไปและในองค์ประกอบส่วนหัวของฉันฉันเพิ่งทำสิ่งนี้

const scroll = () => {
  const section = document.querySelector( '#contact-us' );
  section.scrollIntoView( { behavior: 'smooth', block: 'start' } );
};

2

ทำตามขั้นตอนเหล่านี้:

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>
    )
  }
}

2

นี่คือข้อมูลโค้ดของClass Component ที่คุณสามารถใช้เพื่อแก้ไขปัญหานี้:

วิธีนี้ใช้การอ้างอิงและเลื่อนไปยังการอ้างอิงเป้าหมายได้อย่างราบรื่น

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>
    )
  }
}

1

อะไรที่ทำให้ฉัน:

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>
        )
    }
}

1

เพิ่งขึ้นไปฉันไม่สามารถแก้ปัญหาเหล่านี้เพื่อทำงานกับส่วนประกอบ UI วัสดุ ดูเหมือนว่าพวกเขาไม่มีcurrentทรัพย์สิน

ฉันเพิ่งเพิ่มว่างdivในหมู่องค์ประกอบของฉันและตั้งเสาอ้างอิงที่


1

element.scrollIntoView({ behavior: 'smooth' })วิธีที่ดีที่สุดคือการใช้งาน องค์ประกอบนี้เลื่อนลงในมุมมองด้วยภาพเคลื่อนไหวที่ดี

เมื่อคุณรวมเข้ากับปฏิกิริยาของ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 คุณจะต้องส่งต่อการอ้างอิงไปยังองค์ประกอบที่แสดงผล บทความนี้จะดำน้ำลึกเข้าไปในปัญหาที่เกิดขึ้น



0

สำหรับผู้อื่นที่อ่านข้อความนี้ซึ่งไม่ได้โชคดีมากกับโซลูชันด้านบนหรือเพียงแค่ต้องการใช้งานแบบง่ายๆแพคเกจนี้ใช้ได้สำหรับฉัน: https://www.npmjs.com/package/react-anchor-link- เรียบเลื่อน แฮ็คมีความสุข!


0

ฉันใช้สิ่งนี้ภายในฟังก์ชั่น onclick เพื่อเลื่อนไปยัง div ที่ id ของมันคือ "step2Div"

let offset = 100;
window.scrollTo({
    behavior: "smooth",
    top:
    document.getElementById("step2Div").getBoundingClientRect().top -
    document.body.getBoundingClientRect().top -
    offset
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.