我有一个项目列表(示例名称)。我正在尝试在列表中显示所选项目。
.所选项目有 selected
将为该元素添加边框的类。
.selected {
border: 1px solid blue;
}
选择的项目用变量 const selectedItem = 1;
决定如果是 1
它将选择 second
项目。如果 const selectedItem = 0;
它将选择第一个元素。问题与陈述
className="container"
宽度为 200px
.它将包含尽可能多的列表元素。这取决于项目宽度。 示例 列表项目 (参见示例 1,它仅显示三个项目,因为所有文本都很小。)
const data = [
{ title: "xahsdha" },
{ title: "hello" },
{ title: "hessllo" },
{ title: "hesslssslo" },
{ title: "navveiii" }
];
带有新数据的示例 2:请参阅第一个项目文本很大。它只显示一项。
const data = [
{ title: "xahsdhaadasdasdasdass" },
{ title: "hello" },
{ title: "hessllo" },
{ title: "hesslssslo" },
{ title: "navveiii" }
];
问题 :
我无法选择超出容器的那个项目。
示例 给定数据
const data = [
{ title: "xahsdh" },
{ title: "hello" },
{ title: "hessllo" },
{ title: "hesslssslo" },
{ title: "navveiii" }
];
如果我给 常量选定项 = 1; 我的输出和预期输出相同 .看到我能够显示选定的项目
但如果我给 常量选定项 = 3; 具有相同的数据集
我的输出是
但预期的输出是
如果隐藏元素被选中,我们可以向前移动它吗?
场景二
例如,如果我们通过
const selectedItem = 3
;有了这个数据集
const data = [
{ title: "xahsdh" },
{ title: "hello" },
{ title: "hessllo" },
{ title: "hesslsssloasdasdasdasdasdsa" },
{ title: "navveiii" }
];
预期的输出是这个这个功能可行吗?
这是我的代码
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>
编辑
由于想法是在可见区域中具有当前选定的项目,然后只有数组中从数组开头的那些元素仍然合适,也可见,我们可以修改上述解决方案来代替做出假设当前选定的项目将始终适合。
首先从可用性中减去所选项目的大小,然后从数组的开头进行迭代。如果当前索引与当前选定的索引不匹配,则将当前元素插入可见数组,如果合适则从可用性中减去。如果当前正在查看所选项目,请将其插入可见数组。
对于这个算法和渲染,我为每个项目添加了一个 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>
关于javascript - 如何在 react js中显示选定的项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68263981/