javascript - 如何在 react js中显示选定的项目?

标签 javascript reactjs

我有一个项目列表(示例名称)。我正在尝试在列表中显示所选项目。
.所选项目有 selected将为该元素添加边框的类。

.selected {
  border: 1px solid blue;
}
选择的项目用变量 const selectedItem = 1; 决定如果是 1它将选择 second项目。如果 const selectedItem = 0;它将选择第一个元素。
问题与陈述
  • 我有包装 div className="container"宽度为 200px .它将包含尽可能多的列表元素。这取决于项目宽度。

  • 示例 列表项目 (参见示例 1,它仅显示三个项目,因为所有文本都很小。)
    const data = [
      { title: "xahsdha" },
      { title: "hello" },
      { title: "hessllo" },
      { title: "hesslssslo" },
      { title: "navveiii" }
    ];
    
    enter image description here
    带有新数据的示例 2:请参阅第一个项目文本很大。它只显示一项。
    const data = [
      { title: "xahsdhaadasdasdasdass" },
      { title: "hello" },
      { title: "hessllo" },
      { title: "hesslssslo" },
      { title: "navveiii" }
    ];
    
    enter image description here
    问题 :
    我无法选择超出容器的那个项目。
    示例 给定数据
    const data = [
      { title: "xahsdh" },
      { title: "hello" },
      { title: "hessllo" },
      { title: "hesslssslo" },
      { title: "navveiii" }
    ];
    
    如果我给 常量选定项 = 1;
    我的输出和预期输出相同 .看到我能够显示选定的项目
    enter image description here
    但如果我给 常量选定项 = 3; 具有相同的数据集
    我的输出是
    enter image description here
    但预期的输出是
    enter image description here
    如果隐藏元素被选中,我们可以向前移动它吗?
    场景二
  • 我们还需要注意隐藏元素的宽度。所以选定的项目宽度取决于我将在容器中显示多少项目。

  • 例如,如果我们通过 const selectedItem = 3 ;
    有了这个数据集
    const data = [
      { title: "xahsdh" },
      { title: "hello" },
      { title: "hessllo" },
      { title: "hesslsssloasdasdasdasdasdsa" },
      { title: "navveiii" }
    ];
    
    预期的输出是这个
    enter image description here
    这个功能可行吗?
    这是我的代码
    https://codesandbox.io/s/unruffled-hellman-hswdl?file=/src/App.js
    import "./styles.css";
    import React, { createRef, useMemo, useRef } from "react";
    const data = [
      { title: "xahsdh" },
      { title: "hello" },
      { title: "hessllo" },
      { title: "hesslssslo" },
      { title: "navveiii" }
    ];
    const selectedItem = 1;
    export default function App() {
      const arrLength = data.length;
      const [defaultState, setDefaultState] = React.useState(true);
    
      const elRefs = useMemo(
        () => Array.from({ length: data.length }).map(() => createRef()),
        []
      );
      const [state, setState] = React.useState({
        total: 0,
        tabWidth: 0,
        dimension: {}
      });
      const ulRef = useRef(null);
    
      React.useEffect(() => {
        setDimention();
      }, []);
    
      const setDimention = () => {
        let total = ulRef.current.offsetWidth,
          dimension = {},
          tabWidth = 0;
        console.log(total);
        elRefs.forEach((item, i) => {
          dimension[i] = item.current?.offsetWidth || 0;
          tabWidth += item.current?.offsetWidth || 0;
        });
        console.log({
          total,
          dimension,
          tabWidth
        });
        setDefaultState(false);
        setState({
          total,
          dimension,
          tabWidth
        });
      };
    
      const getTabs = () => {
        const { tabWidth, dimension, total } = state;
        var visible = [],
          avaiable = total,
          hidden = [];
        if (defaultState) {
          return {
            visible,
            hidden
          };
        }
        data.forEach((element, index) => {
          if (avaiable - dimension[index] > 0) {
            visible.push(element);
            avaiable = avaiable - dimension[index];
          } else {
            hidden.push(element);
          }
        });
        return {
          visible,
          hidden
        };
      };
      const { visible = [], hidden = [] } = getTabs();
      return (
        <div className="container" ref={ulRef}>
          <ul id="dummy">
            {visible.length === 0 &&
              hidden.length === 0 &&
              data.map((el, i) => (
                <li
                  className={i === selectedItem ? "selected" : ""}
                  ref={elRefs[i]}
                  key={i}
                >
                  {el.title}
                </li>
              ))}
          </ul>
          <ul id="visible">
            {visible.map((el, i) => (
              <li className={i === selectedItem ? "selected" : ""} key={i}>
                {el.title}
              </li>
            ))}
          </ul>
          <ul id="hidden">
            {hidden.map((el, i) => (
              <li className="hide" key={i}>
                {el.title}
              </li>
            ))}
          </ul>
        </div>
      );
    }
    
    注意和更新 :我不想要可滚动列表。我希望优先考虑“选定”项目,如果有可用空间,请在前面添加其他元素。
    有什么建议吗?
    在 jQuery 中是可能的。所以确定我们是否在 react 中实现了这一点。我检查了这个 jQuery 示例选定的项目在最后,但它仍然出现在 View 中
    https://codepen.io/naveennsit/pen/poPJOPM?editors=1010

    最佳答案

    我认为这里的主要问题是确定在 时应该显示哪些元素不是 从头渲染。
    我建议从当前选定的项目和可见偏移量开始计算可见和隐藏元素的数组。首先逆向计算向 移动的可见/隐藏元素正面 数组,然后从元素 开始执行第二个循环之后 所选项目向 移动结束的数组。

    const getTabs = () => {
      const { dimension, total } = state;
    
      const visible = [];
      const hidden = [];
    
      let offset = 0;
      let available = total;
    
      if (!initialRender) {
        // check forward
        for (let i = selectedItem; i >= 0; i--) {
          if (available > dimension[i]) {
            visible.unshift(data[i]);
            available -= dimension[i];
          } else {
            hidden.unshift(data[i]);
            offset++;
          }
        }
    
        // check aft
        for (let i = selectedItem + 1; i < arrLength; i++) {
          if (available > dimension[i]) {
            visible.push(data[i]);
            available -= dimension[i];
          } else {
            hidden.push(data[i]);
          }
        }
      }
    
      return {
        hidden,
        offset,
        visible
      };
    };
    
    在渲染可见和隐藏数组时,只需将当前映射的索引+偏移量与当前选定的项索引进行比较即可。
    <ul id="visible">
      {visible.map((el, i) => (
        <li
          className={i + offset === selectedItem ? "selected" : ""}
          key={i}
        >
          {el.title}
        </li>
      ))}
    </ul>
    <ul id="hidden">
      {hidden.map((el, i) => (
        <li className="hide" key={i}>
          {el.title}
        </li>
      ))}
    </ul>
    
    Edit how-to-show-selected-item-in-react-js
    编辑
    由于想法是在可见区域中具有当前选定的项目,然后只有数组中从数组开头的那些元素仍然合适,也可见,我们可以修改上述解决方案来代替做出假设当前选定的项目将始终适合。
    首先从可用性中减去所选项目的大小,然后从数组的开头进行迭代。如果当前索引与当前选定的索引不匹配,则将当前元素插入可见数组,如果合适则从可用性中减去。如果当前正在查看所选项目,请将其插入可见数组。
    对于这个算法和渲染,我为每个项目添加了一个 GUID。
    const data = [
      { title: "xahsdh", id: uuidV4() },
      { title: "hello", id: uuidV4() },
      { title: "hessllo", id: uuidV4() },
      { title: "hesslssslo", id: uuidV4() },
      { title: "navveiii", id: uuidV4() },
    ];
    
    ...
    
    const getTabs = () => {
      const { dimension, total } = state;
    
      const visible = [];
      const hidden = [];
    
      const selectedIndex = data.findIndex((el) => el.id === selectedItem);
      if (!initialRender && selectedIndex !== -1) {
        let available = total - dimension[selectedIndex];
    
        data.forEach((el, i) => {
          if (i === selectedIndex) {
            visible.push(el);
            return;
          }
          if (available > dimension[i]) {
            visible.push(el);
            available -= dimension[i];
          } else {
            hidden.push(el);
          }
        });
      }
    
      return {
        hidden,
        visible
      };
    };
    
    渲染时检查 GUID。
    <ul id="visible">
      {visible.map((el, i) => (
        <li
          className={el.id === selectedItem ? "selected" : ""}
          key={el.id}
        >
          {el.title}
        </li>
      ))}
    </ul>
    <ul id="hidden">
      {hidden.map((el, i) => (
        <li className="hide" key={el.id}>
          {el.title}
        </li>
      ))}
    </ul>
    
    Edit how-to-show-selected-item-in-react-js (forked)

    关于javascript - 如何在 react js中显示选定的项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68263981/

    相关文章:

    javascript - 删除除子项之外的所有内容

    javascript - 将文本框传输到文本区域时附加新行(JQuery)

    javascript - 基于哪个onclick,如何使用JS使用 'srcset'更改img src?

    javascript - 密码重置 token GET 请求不起作用

    javascript - React - 用逗号解析用户输入的值并删除 CR/LF 和空格

    javascript - React,使用 localStorage 实现暗光模式

    javascript - 在响应式断点上执行 unslick() 的语法

    javascript - 为什么 URL 不被放入状态数组中?

    javascript - 在 React 中,单击后设置元素的样式不起作用

    javascript - 如何将列表附加到 FormData?