【问题标题】:scrollIntoView whole page shifting downscrollIntoView 整个页面向下移动
【发布时间】:2020-06-03 09:50:36
【问题描述】:

我想建立一个索引字母。当我单击字母时(例如 A、B、C)。它应该滚动到所属的标题。我在这里使用了 scrollIntoView 。一切都好,除了“block:start”。当我想滚动到开始的标题时,整个页面滚动容器。

这是我关于问题的 gif 图像

这是我的 html & css & javascript 代码。

const scrollTo = id => {
let ref = document.getElementById(id)
if (ref /* + other conditions */) {
  ref.scrollIntoView({
    behavior: "smooth",
    block: "start",
    inline: "start",
  })
}

}

<div className="glossary">
    <div className="glossary-items grid">
      <div className="d-flex ">
        <div className="glossary-letters ">
          <ul>
            {letter.map(item => (
              <li onClick={() => scrollTo(item)}>
                <a> {item}</a>
              </li>
            ))}
          </ul>
        </div>
        <div className="glossary-titles">
          <ul>
            {glossary.map((item, index) => (
              <div key={item.group}>
                <li id={item.group}>{item.group}</li>
                {item.children.map((item2, i) => (
                  <li key={i}>
                    <Link
                      activeClassName="glossary-titles-active"
                      to={`/en/sozluk/${item2.first_name + item2.id}`}
                    >
                      {item2.first_name}
                    </Link>
                  </li>
                ))}
              </div>
            ))}
          </ul>
        </div>
      </div>
      <div className="glossary-content ml-5">
        <Router>
          <Glossary path="en/sozluk/:id" />
        </Router>
      </div>
    </div>
  </div>

【问题讨论】:

  • 我刚刚意识到您可以传递一个布尔参数,并将其设置为 false 对我有用:myRef.current.scrollIntoView(false)

标签: javascript css reactjs scrollview js-scrollintoview


【解决方案1】:

There is related question to that

您可以使用父元素的scrollTo 函数滚动到特定的子元素。

示例

const { useState, useEffect, useRef } = React;
const App = () => {
  const [list, setList] = useState([]);
  const [keywords, setKeywords] = useState([]);
  const refs = useRef(null);
  const parentRef = useRef(null);
  
  useEffect(() => {
    const newList = Array(25).fill(0).map((pr, index) => String.fromCharCode(65 + index));
    const newKeywords = newList.flatMap(pr => [pr, ...newList.map(npr => pr + npr)]);
    
    refs.current = newList.reduce((acc, letter) => {
      acc[letter] = React.createRef();
      return acc;
    }, {});
    
    setList(newList);
    setKeywords(newKeywords);
  }, [])
  
  const onClick = ({target: {dataset: {letter}}}) => {
    const element = refs.current[letter].current;
    const parent = parentRef.current;
    
    const onScroll = () => {
      const relativeTop = window.scrollY > parent.offsetTop ? window.scrollY : parent.offsetTop
    
      parent.scrollTo({
        behavior: "smooth",
        top: element.offsetTop - relativeTop
      });
    }
    
    window.removeEventListener("scroll", onScroll);
    window.addEventListener("scroll", onScroll);
    
    onScroll();
    
    /*
    element.scrollIntoView({
      behavior: "smooth",
      block: "start",
      inline: "start",
    })
    */
  }
  
  const tryAssignRef = (letter) => {
    return list.indexOf(letter) > -1 ? {ref: refs.current[letter]} : {};
  }

/// ...{ref: {refs.current['A']}}
  return <div className="container">
    <div className="header">
    </div>
    <div className="body">
      <div className="left">
        <div className="letters">{list.map(pr => <div className="letter" onClick={onClick} data-letter={pr} key={pr}>{pr}</div>)}</div>
        <div ref={parentRef} className="keywords">{keywords.map(pr => <div {...tryAssignRef(pr)} key={pr}>{pr}</div>)}</div>
      </div>
      <div className="right">
      </div>
    </div>
  </div>
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
  );
.container, .body, .left {
  display: flex;
}

.container {
  flex-direction: column;
}

.header {
  flex: 0 0 100px;
  border: 1px solid black;
}

.body {
  height: 1000px;
}

.left {
  flex: 1;
}

.right {
  flex: 2;
}

.left { 
  justify-content: space-between;
}

.letter {
  padding: 2px 0;
  cursor: pointer;
}

.letters, .keywords {
  padding: 0 10px;
}

.keywords {
  overflow-y: scroll;
}
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>

【讨论】:

  • 感谢您的回答。我也找到了一个简单的解决方案。您可以在相对 div(词汇表容器)上提供一个 id 并使用 scrollTop 函数。 var topPos = ref.offsetTop document.getElementById("glossary-container").scrollTop = topPos - 143
  • 我避免在 React 中使用 document.getElement*。最好使用 ref
  • 感谢推荐。为什么我应该使用 ref 而不是 document.getElement* ?
  • 这是反应世界。你不知道元素什么时候会出现
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-07
相关资源
最近更新 更多