我正在处理一个小部分,我必须水平显示大约divs个,所以当它超出空间时,我使用css作为overflow-x:auto,这样它就可以滚动了.

What I did

<div className="App d-flex">
  {data.map((li) => {
    return (
      <div key={li.id} className="boxes">
        {li.name}
      </div>
    );
  })}
</div>

我的下面的css

.d-flex {
  display: flex;
}
.boxes {
  padding: 12px;
  margin: 4px;
  background-color: rgb(196, 218, 243);
  min-width: 150px;
  overflow-x: auto;
  text-align: center;
  border-radius: 6px;
}

What I am trying to do

  • 我想把点放在那里,这样当用户点击点时,它应该滚动.
  • 这些点应该只在超过一定数量的项目时触发,这意味着如果一个屏幕上可以显示的项目较少,则没有点或其他点.
  • 在这里,我不明白如何使用react 钩子来实现这一点.

Here is my Code SandBox

Edit I am trying to get This

此外,当滚动时,它应该只滚动该部分的整个页面.

推荐答案

您需要:

  • 保持视区宽度并允许滚动的外部容器.
  • 与内容一起增长并溢出外部div的内部容器.

Css如下

.outer-container {
  width: 100%;
  overflow-x: auto;
}

.inner-container {
  width: max-content;
}

使用Resive Observer API来监听任一容器何时调整大小.外容器将在视区大小更改时调整大小,而内容器将在内容更改时调整大小.

如果内容器比外容器大,只需显示导航菜单即可.

  useEffect(() => {
    const outerContainer = outerContainerRef.current;
    const innerContainer = innerContainerRef.current;
    if (!outerContainer || !innerContainer) return;

    const observer = new ResizeObserver(() => {
      setShowNavigation(innerContainer.clientWidth > outerContainer.clientWidth);
    });

    observer.observe(outerContainer);
    observer.observe(innerContainer);

    // Cleanup
    return () => observer.disconnect();
  }, [outerContainerRef.current, innerContainerRef.current]);

在下面的例子中,为了简化,我使用了箭头和左右滚动.制作这些点比较复杂,因为它涉及计算要显示多少个点,并跟踪它们的状态.我相信你能从那里弄明白的.


Snippet Example

let data = [
  {
    name: 'steve',
    id: 1,
  },
  {
    name: 'Matt',
    id: 2,
  },
  {
    name: 'michel',
    id: 3,
  },
  {
    name: 'Morgan',
    id: 4,
  },
  {
    name: 'joss',
    id: 5,
  },
  {
    name: 'stephen',
    id: 6,
  },
  {
    name: 'clark',
    id: 7,
  },
  {
    name: 'Simmons',
    id: 8,
  },
  {
    name: 'Chris',
    id: 9,
  },
  {
    name: 'Beven',
    id: 10,
  },
];

function App() {
  const outerContainerRef = React.createRef();
  const innerContainerRef = React.createRef();
  const [showNavigation, setShowNavigation] = React.useState(false);
  const [num, setNum] = React.useState(3);

  React.useEffect(() => {
    const outerContainer = outerContainerRef.current;
    const innerContainer = innerContainerRef.current;
    if (!outerContainer || !innerContainer) return;

    const observer = new ResizeObserver(() => {
      setShowNavigation(innerContainer.clientWidth > outerContainer.clientWidth);
    });

    observer.observe(outerContainer);
    observer.observe(innerContainer);

    // Cleanup
    return () => observer.disconnect();
  }, [outerContainerRef.current, innerContainerRef.current]);

  function scrollRight() {
    outerContainerRef.current.scrollBy(outerContainerRef.current.clientWidth, 0);
  }

  function scrollLeft() {
    outerContainerRef.current.scrollBy(-outerContainerRef.current.clientWidth, 0);
  }

  function add() {
    setNum((num) => Math.min(num + 1, data.length));
  }

  function remove() {
    setNum((num) => Math.max(num - 1, 0));
  }

  return (
    <div>
      <div className="outer-container d-flex" ref={outerContainerRef}>
        <div className="inner-container d-flex" ref={innerContainerRef}>
        {data.slice(0, num).map((li) => {
          return (
            <div key={li.id} className="boxes">
              {li.name}
            </div>
          );
        })}
        </div>
      </div>
      <div className="arrow-container">
        {showNavigation && (
          <React.Fragment>
            <button className="left-arrow" onClick={scrollLeft}>
              {'<'}
            </button>
            <button className="right-arrow" onClick={scrollRight}>
              {'>'}
            </button>
          </React.Fragment>
        )}
      </div>
      <button onClick={add}>ADD</button>
      <br />
      <br/>
      <button onClick={remove}>REMOVE</button>
    </div>
  );
}


const rootElement = document.getElementById('root');
const root = ReactDOM.createRoot(rootElement);
root.render(<App />);
.d-flex {
  display: flex;
}

.outer-container {
  width: 100%;
  overflow-x: auto;
}

.inner-container {
  width: max-content;
}

.boxes {
  padding: 12px;
  margin: 4px;
  background-color: rgb(196, 218, 243);
  min-width: 150px;
  text-align: center;
  border-radius: 6px;
}

.arrow-container {
  height: 2em;
}

.right-arrow {
  position: absolute;
  right: 8px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.production.min.js"></script>

<div id="root"></div>


Stackblitz Typescript example

https://stackblitz.com/edit/react-ts-rq7fnm?file=App.tsx

Javascript相关问答推荐

v-textfield的规则找不到数据中声明的元素

如何在非独立组件中使用独立组件?

我的glb文件没有加载到我的three.js文件中

禁用从vue.js 2中的循环创建的表的最后td的按钮

在分区内迭代分区

D3多线图显示1线而不是3线

Redux工具包查询(RTKQ)端点无效并重新验证多次触发

类型脚本中只有字符串或数字键而不是符号键的对象

jQuery提交按钮重新加载页面,即使在WordPress中使用preventDefault()

使用javascript将Plotly Expandable Sparkline转换为HighCharter Plot在bslib卡中

将字符串UTC Date转换为ngx—counting leftTime配置值的数字

当点击注册页面上的注册按钮时,邮箱重复

在Matter.js中添加从点A到另一个约束的约束

查询参数未在我的Next.js应用路由接口中定义

如何在不影响隐式类型的情况下将类型分配给对象?

查询参数中的JAVASCRIPT/REACT中的括号

元素字符串长度html

在Odoo中如何以编程方式在POS中添加产品

Node.js API-queryAll()中的MarkLogic数据移动

如何在尚未创建的鼠标悬停事件上访问和着色div?