programing

React(반응)에서 오버플로우 div(div)의 맨 아래로 스크롤합니다.

newnotes 2023. 4. 5. 22:12
반응형

React(반응)에서 오버플로우 div(div)의 맨 아래로 스크롤합니다.

나는 가지고 있다ul와 함께max-height그리고.overflow-y: auto.

사용자가 충분히 입력했을 때li요소,ul스크롤이 시작되지만 마지막은li와 함께form사용자에게 항상 표시되도록 합니다.

실장해 보았습니다.scrollToBottom다음과 같은 기능을 수행합니다.

scrollToBottom() {
    this.formLi.scrollIntoView({ behavior: 'smooth' });
}

하지만 그것은 단지ul화면 맨 위로 점프하여 를 표시하다li그 안에 형체가 보이는 유일한 것으로서 말이야

더 좋은 방법이 있을까요?제가 찾은 답변은 조금 더 나이가 들어 React DOM을 사용하는 경향이 있습니다.감사합니다!

CSS:

.prompt-box .options-holder {
    list-style: none;
    padding: 0;
    width: 95%;
    margin: 12px auto;
    max-height: 600px;
    overflow-y: auto;
}

HTML:

<ul className='options-holder'>
    {
        this.state.items.map((item, index) => (
            <li key={item.id} className={`option ${index === 0 ? 'first' : ''}`}>
                <div className='circle' onClick={this.removeItem} />

                <p className='item-text'>{ item.text }</p>
            </li>
        ))
    }

    <li key={0} className={`option form ${this.state.items.length === 0 ? 'only' : ''}`} ref={el => (this.formLi = el)}>
        <div className='circle form' />

        <form className='new-item-form' onSubmit={this.handleSubmit}>
            <input 
                autoFocus 
                className='new-item-input' 
                placeholder='Type something and press return...' 
                onChange={this.handleChange} 
                value={this.state.text}
                ref={(input) => (this.formInput = input)} />
        </form>
    </li> 
</ul>

페이지 높이를 채우는 용기가 있어요.이 용기에는 디스플레이 플렉스 및 플렉스 방향 열이 있습니다.그러면 저는Messages의 컴포넌트ul하나와 함께li메시지별 및 특집AlwaysScrollToBottom마지막 아이로서의 컴포넌트는 의 도움을 받아 들인다.useEffect목록 맨 아래까지 스크롤합니다.

const AlwaysScrollToBottom = () => {
  const elementRef = useRef();
  useEffect(() => elementRef.current.scrollIntoView());
  return <div ref={elementRef} />;
};

const Messages = ({ items }) => (
  <ul>
    {items.map(({id, text}) => <li key={id}>{text}</li>)}
    <AlwaysScrollToBottom />
  </ul>
)

const App = () => (
  <div className="container">
    <Messages items={[...]}>
    <MessageComposer />
  </div>
)

CSS는

.container {
  display: flex;
  height: 100vh;
  flex-direction: column;
}

ul {
  flex-grow: 1;
  overflow-y: auto;
}

MessageComposer는 간결성을 위해 생략되었으며 메시지 발송 양식, 입력 필드 등이 포함되어 있습니다.

react-scroll 라이브러리를 사용합니다.단, 사용자 ID를 명시적으로 설정해야 합니다.ul.

import { animateScroll } from "react-scroll";

scrollToBottom() {
    animateScroll.scrollToBottom({
      containerId: "options-holder"
    });
}

전화하시면 됩니다.scrollToBottomsetState 콜백으로 설정합니다.

예를들면

this.setState({ items: newItems}, this.scrollToBottom);

또는 set Timeout을 사용합니다.

또는 설정도 가능합니다.Element부터react-scroll특정 위치로 스크롤합니다.li.

사용자 Import에서 가져온 컴포넌트의 배열을 렌더링할 때도 비슷한 문제가 있었습니다.저는 componentDidUpdate() 함수를 사용하여 제 기능을 수행하게 되었습니다.

componentDidUpdate() {
        // I was not using an li but may work to keep your div scrolled to the bottom as li's are getting pushed to the div
        const objDiv = document.getElementById('div');
        objDiv.scrollTop = objDiv.scrollHeight;
      }

채팅 같은 인터페이스를 만들고 있는 것 같네요.포장해 보세요.<ul>및 그div.circle-form다음과 같이 별도의 div로 지정합니다.

ul{
  border:1px solid red;
  height:13em;
  overflow-y:auto;
  position:relative;
}
ul li{
  border-bottom:1px solid #ddd;
  list-style:none;
  margin-left:0;
  padding:6px;
}

.wrapper{
  background:#eee;
  height:15em;
  position:relative;
}
.circle-form{
  background:#ddd;
  height:2em;
  padding:3px;
  position:absolute;
  bottom:0;
  left:0;
  right:0;
  z-index:2;
}
.circle-form input[type=text]{
  padding:8px;
  width:50%;
}
<div class="wrapper">
   <ul id="list">
       <li>item</li>
       <li>item</li>
       <li>item</li>
       <li>item</li>
       <li>item</li>
       <li>item</li>
       <li>item</li>
       <li>item</li>
    </ul>
    <div class="circle-form">
        <input type="text" name="type_here" placeholder="Enter something..." autofocus/>
    </div>
</div>

편집

javascript를 사용하여 목록 맨 아래로 스크롤하려면

var list = document.getElementById("list");
list.scrollTop = list.offsetHeight;

프로젝트 중 하나에서 상단을 부드럽게 스크롤하기 위해 사용한 스크립트가 있습니다. 저는 작은 리팩터를 만들어서 div(아래쪽 스크롤)의 높이를 스크롤했습니다.도움이 됐으면 좋겠어요.

스크롤.스크린

function currentYPosition() {
  if (self.pageYOffset) return self.pageYOffset;
  if (document.documentElement && document.documentElement.scrollHeight) return document.documentElement.scrollHeight;
  if (document.body.scrollHeight) return document.body.scrollHeight;

  return 0;
}

function elmYPosition(eID) {
  let elm = document.getElementById(eID);
  let y = elm.offsetHeight;
  let node = elm;
  while (node.offsetParent && node.offsetParent != document.body) {
    node = node.offsetParent;
    y += node.offsetHeight;
  }
  return y;
}

export default function smoothScroll(eID, string) {
  let startY = currentYPosition();
  let stopY = elmYPosition(eID);
  let distance = stopY > startY ? stopY - startY : startY - stopY;
  let speed = Math.round(distance / 10);
  let speedTimeout = 250;
  if (speed >= 100) speed = 100;
  if (string) speed = 1;
  let step = Math.round(distance / 25);
  let leapY = stopY > startY ? startY + step : startY - step;
  let timer = 0;
  if (stopY > startY) {
    for (let i = startY; i < stopY; i += step) {
      setTimeout('window.scrollTo(0, ' + leapY + ')', timer * speed);
      leapY += step;
      if (leapY > stopY) leapY = stopY;
      timer++;
    }
    return;
  }
  for (let i = startY; i > stopY; i -= step) {
    setTimeout('window.scrollTo(0, ' + (leapY) + ')', timer * speed);
    leapY -= step;
    if (leapY < stopY){
      leapY = stopY;
    } 
    timer++;
  }
}

컴포넌트 내에 Import해야 합니다.파라미터는 2개입니다(이 경우 ref를 사용할 수 있습니다).두 번째는 스크롤 속도를 처리하기 위해 사용한 스트링입니다.

import scroll from './your-path/scroll.js';
.
.
.
<ul className='options-holder'>
{
    this.state.items.map((item, index) => (
        <li key={item.id} className={`option ${index === 0 ? 'first' : ''}`} ref={el => (this.formLi = el)}>
            <div className='circle' onClick={this.removeItem} />

            <p className='item-text'>{ item.text }</p>
        </li>
    ))
}

<li key={0} className={`option form ${this.state.items.length === 0 ? 'only' : ''}`} ref={el => (this.formLi = el)}>
    <div className='circle form' />

    <form className='new-item-form' onSubmit={this.handleSubmit}>
        <input 
            autoFocus 
            className='new-item-input' 
            placeholder='Type something and press return...' 
            onChange={this.handleChange} 
            value={this.state.text}
            ref={(input) => (this.formInput = input)} />
    </form>
</li> 

렌더 내에서 이 LI를 매핑하는 방법을 알고 있지만 확인을 하고 Overflow 속성이 있는 경우 스크롤을 실행해야 합니다.

컴포넌트가 첫 번째 요소로 이동하면 마지막 요소가 아닌 첫 번째 요소의 참조를 참조할 수 있습니다.

생각할 수 있는 회피책:

scroll(this.state.items[this.state.items.length - 1]);

업데이트 1: 원본 스크롤.js의 Gist, 맨 위로 스크롤

'만들기'를 사용하세요.position:sticky이치

li:last-child {
  position:sticky;
  bottom:0;
}

데모

카니우스

특정 컴포넌트 이외에서 동작하는 범용 기능을 사용하여 해결했습니다.상위 요소(목록 상자, 여러 줄 편집 등)와 마지막 하위 요소(또는 스크롤할 위치)에 대한 참조를 정의해야 합니다.

export const scrollToRef = (parentRef, childRef) => {
    trace("scrollToRef:ref.current.offsetTop", childRef.current.offsetTop);
    parentRef.current.scrollTo(0, childRef.current.offsetTop)
}

기능 컴포넌트로 사용하고 있으며, 부모 컨테이너가 갱신될 때마다 효과라고 부릅니다.

Flexbox 대신 CSS Grid를 사용하고 있기 때문에 이 답변은 그다지 효과가 없었습니다.div하다

저는 설명했습니다.ref그리고 마지막 아이를 로 가져옵니다.

import { useEffect } from 'react'

export const useScrollToBottom = ref => {
  useEffect(() => {
    ref?.current?.querySelector(':scope > :last-child')?.scrollIntoView()
  }, [ref])
}
const Messages = ({ items }) => {
  const scrollContainer = useRef()
  useScrollToBottom(scrollContainer)

  return (
    <ul ref={scrollContainer}>
      {items.map(({id, text}) => <li key={id}>{text}</li>)}
    </ul>
  )

이를 수행하려면 "아래로 스크롤 반응" 모듈을 사용할 수 있습니다.

새 아이가 추가되면 아래로 자동 스크롤합니다.

import ScrollToBottom from 'react-scroll-to-bottom';

<ScrollToBottom className={ROOT_CSS}>
   <p>
       Nostrud nisi duis veniam ex esse laboris consectetur officia et. Velit 
       cillum est veniam culpa magna sit
  </p>
</ScrollToBottom>

링크: https://www.npmjs.com/package/react-scroll-to-bottom

언급URL : https://stackoverflow.com/questions/45719909/scroll-to-bottom-of-an-overflowing-div-in-react

반응형