问题描述
我使用 react-grid-layout 来制作 drag-drop and resize components
,所以我能够实现文档中提到的功能。
我的问题
- 我正在创建动态 UI,因此我正在使用数据渲染我的 UI。
- 在这个库中,我需要创建布局,如
{ {i: 'a',x: 0,y: 0,w: 1,h: 2}
- 当我创建静态 UI 时,我能够实现我想要的。Here is working code sandbox
在具有预定义布局的静态 UI 中,我喜欢下面的内容。
const layout = [
{ i: "a",w: 2,h: 1 },{ i: "b",x: 2,{ i: "c",x: 4,{ i: "d",x: 6,{ i: "e",y: 2,h: 1 }
];
<div className="App">
<GridLayout
className="layout"
layout={layout}
style={{ backgroundColor: "blue" }}
>
{layout.map((li) => (
<div key={li.i} style={{ backgroundColor: "yellow" }}>
{li.i}
</div>
))}
</GridLayout>
这工作正常,但这里我定义的布局是静态的,所以为此我搜索并得到了一个动态高度和宽度的例子,它正在创建一个动态布局。
但这只是使用随机数创建布局,而我的用户界面并未显示这些数字(根据我的使用情况),This is what I found out in library for dynamic UI
我想做什么
我有这个数据,就像我的状态
const [data1,setData] = useState({
EmpData: [
{
empId: 11,lay1: { i: 'a' },data: [
{
firstName: 'Steve',lastName: 'Smith',},{
firstName: 'Michel',lastName: 'Muner',],{
empId: 12,lay1: { i: 'b' },data: [
{
firstName: 'Charles',lastName: 'Johnsen',{
firstName: 'Glen',lastName: 'Tyson',{
empId: 13,lay1: { i: 'c' },{
empId: 14,lay1: { i: 'd' },{
empId: 15,lay1: { i: 'e' },});
根据以上数据,我根据需要创建了 Ui
return data1.EmpData.map((li,index) => (
<div key={index.toString()} data-grid={index}"> </div> //what should I pass here as key and layout that I am not getting
<>
{li.data.map((l) => (
<>
<div>{l.firstName}</div>
<div>{l.lastName}</div>
</>
))}
</>
</div>
));
};
传递 key
并创建动态 layout
是我无法弄清楚如何实现这一点的地方,因为这对我来说是全新的事情。
我的 UI 是完全动态的每次我要获取动态数据时,我都需要显示很多卡片或 div。
Here is my code sand box what I am trying to do dynamically
编辑/更新
我从 @Daniil Loban
得到的答案非常有帮助,但是当我尝试使用实时数据进行循环时,它会循环两次,这是因为我的数据与我的数据略有不同已在此处显示
实际上我无法理解 I use data1.EmpData[l.i] to get data to display when I map layout.
这一行。
我的数据
[
{
compId: 5,company_name: "Info",comp_data: [
{
empId: 1,empName:"steve"
},{
empId: 2,empName:"meg"
}
]
},{
compId: 6,company_name: "wipro",comp_data: [
{
empId: 11,empName:"mark"
},{
empId: 12,empName:"Tnml"
}
]
}
]
- 数据的流向就像公司->该公司的雇员->该公司的数据,
- 所以这里的公司可以是多个员工,数据也可以是多个类似的
- 我在之前的数据中更新了什么 我没有提到这家公司,因为我想到的是编写最少的代码。
- 我现在添加了完整代码,Here is my code sandbox
问题
-
问题是重复数据,我显示重复数据
-
我会像
company namme->companydata->employe name
这样解释,这应该是完美的,但正在发生的事情是 -- companyname->在一个 div 中都使用了 I a,在另一个 div 中,我同时获得了两个
应该是 Info
有两个雇用,所以在一个网格中一个雇用一个,另一个雇用另一个。
问题出在 generateDOM
这个函数中,因为布局是完美生成的,但是在一个布局中,它对其他布局重复所有然后相同,如果 lenght 是 3,那么它正在创建 3 个布局,这完全没问题,但在一个布局中,它再次循环并显示重复数据
解决方法
我认为问题在于没有使用布局,我还注意到 lodash 中 random 的使用不正确(但这不是必需的)
当我映射 data1.EmpData[l.i]
时,我使用 layout
获取要显示的数据。
我还创建了一个 sandbox,其中有一个用于动态添加的按钮,我认为这正是您想要的。
const generateDOM = () => {
// Generate items with properties from the layout,rather than pass the layout directly
const layout = generateLayout();
return _.map(layout,function (l) {
return (
<div key={l.i} data-grid={l} className="bg-success">
<>
<div className="rounded" key="?"></div>
{data1.EmpData[l.i].data.map((l) => (
<>
<div>{l.firstName}</div>
<div>{l.lastName}</div>
</>
))}
</>
</div>
);
});
};
对于更新的问题:
const generateDOM = (lo) => {
// Generate items with properties from the layout,function (l) {
return (
<div key={l.i} data-grid={l} className="bg-success">
<div>{lo[l.i].empName}</div>
{console.log(lo,l,active_menu)}
</div>
);
});
};
当我们渲染时,we don't need map
,但只有一个调用:
return (
<>
{data1.map((d,ind) => (
<div className={ind === active_menu ? "compNameActive" : "compName"}>
<p onClick={() => compClick(ind)}>{d.company_name}</p>
</div>
))}
<ReactGridLayout onLayoutChange={onLayoutChange} {...props}>
{generateDOM(data1[active_menu].comp_data)}
</ReactGridLayout>
</>
);
,
布局应该是一个包含布局数据的对象,包括一个 id i
来存储与其他数据的关系:
[
{ i: "a",x: 0,y: 0,w: 2,h: 1 },^------- The id to store the relation to other data
]
您需要首先以您选择的方式或直接从您的 emp-data 构建布局。只有 id i
必须匹配您的 emp-data,其他值是“独立”布局数据。
请注意,我的示例要求 empId
是唯一的(您的示例中有重复)。
例如:
const generateLayout = () => {
let totalIndex = -1;
return data1.EmpData.reduce( (accEmp,empItem,empIndex) => {
return accEmp.concat(
empItem.data.map( (dataItem,index) => {
const w = _.random(1,2);
const h = _.random(1,3);
totalIndex++;
return {
x: (totalIndex * 2) % 12,y: Math.floor(totalIndex / 6),w: w,h: h,i: empItem.empId + '-' + index
};
})
);
},[]);
}
然后,要显示内容,您可以遍历 layout 数据,并通过存储在布局中的 id i
找到要显示的元素。
例如:
const generateDOM = () => {
const layout = generateLayout();
return layout.map((ly,index) => {
const [ empIndex,dataIndex ] = ly.i.split('-');
const empItem = data1.EmpData.find( eI => eI.empId.toString() === empIndex );
const dataItem = empItem.data[ dataIndex ];
return (
<div key={ly.i} className="bg-success">
<div className="rounded" key="?"></div>
<>
<div>{dataItem.firstName}</div>
<div>{dataItem.lastName}</div>
</>
</div>
);
});
};
我认为你也可以反过来做,即迭代你的 emp-data,并找到匹配的布局项。但我不确定。