我已经开发了以下ReactJS组件,作为可将相似数据分组在一起的网格的模板:
汽车数据:
let cars = [
{
brand: "Audi",
color: "Red",
year: "1993",
miles: "1234"
},
{
brand: "Audi",
color: "Blue",
year: "1992",
miles: "1234"
},
{
brand: "Audi",
color: "White",
year: "1992",
miles: "1234"
},
{
brand: "Audi",
color: "Red",
year: "1991",
miles: "1234"
},
{
brand: "Audi",
color: "Black",
year: "1995",
miles: "1234"
},
{
brand: "Mercedes",
color: "Red",
year: "1992",
miles: "1234"
},
{
brand: "Mercedes",
color: "Red",
year: "1993",
miles: "1234"
},
{
brand: "Mercedes",
color: "Blue",
year: "1994",
miles: "1234"
},
{
brand: "Mercedes",
color: "Black",
year: "1994",
miles: "1234"
},
{
brand: "Mercedes",
color: "White",
year: "1992",
miles: "1234"
},
{
brand: "BMW",
color: "Red",
year: "1995",
miles: "1234"
},
{
brand: "BMW",
color: "Blue",
year: "1992",
miles: "1234"
},
{
brand: "BMW",
color: "Red",
year: "1994",
miles: "1234"
},
{
brand: "BMW",
color: "Black",
year: "1992",
miles: "1234"
},
{
brand: "BMW",
color: "White",
year: "1993",
miles: "1234"
}
];
组件:
const groupBy = (arr, fields) => {
let field = fields[0];
if (!field) return arr;
let retArr = Object.values(
arr.reduce((obj, current) => {
let val = current[field];
if (!obj[val]) obj[val] = { rows: [] };
obj[val].rows.push(current);
return obj;
}, {})
);
if (fields.length) {
retArr.forEach((obj, index) => {
obj.rows = groupBy(obj.rows, fields.slice(1));
});
}
return retArr;
};
const getRowsFromGrouped = rows => {
let ret = [];
rows.map(row => {
if (row.rows) {
ret = ret.concat(getRowsFromGrouped(row.rows));
} else {
ret.push(row);
}
});
return ret;
};
class App extends Component {
state = {
groups: []
};
handleClick = key => {
let groups = this.state.groups;
let index = groups.findIndex(item => {
return key === item;
});
if (index < 0) groups.push(key);
else groups.splice(index, 1);
this.setState({
groups: groups
});
};
getHeader = row => {
let data = Object.keys(row).map((col, index) => {
return <td key={"Head" + index}>{col}</td>;
});
return (
<thead>
<tr>{data}</tr>
</thead>
);
};
getColumns = row => {
return Object.keys(row).map((col, index) => {
return <td key={"Col" + index}>{row[col]}</td>;
});
};
getRows = rows => {
let data = rows.map((row, index) => {
return <tr key={index}>{this.getColumns(row)}</tr>;
});
return <tbody>{data}</tbody>;
};
renderGrid = rows => {
return (
<table>
{this.getHeader(rows[0])}
{this.getRows(rows)}
</table>
);
};
renderGroupOptions = () => {
return (
<div>
<p>
<input
type="checkbox"
onClick={() => this.handleClick("brand")}
/>
Group By Brand
</p>
<p>
<input
type="checkbox"
onClick={() => this.handleClick("color")}
/>
Group By Color
</p>
<p>
<input
type="checkbox"
onClick={() => this.handleClick("year")}
/>
Group By Year
</p>
</div>
);
};
render = () => {
let rows = cars;
if (this.state.groups.length > 0) {
let data = groupBy(cars, this.state.groups);
rows = getRowsFromGrouped(data);
}
return (
<div>
<h1>AUTO GRID</h1>
{this.renderGrid(rows)}
{this.renderGroupOptions()}
</div>
);
};
}
经开发,分组效果很好。根据组的选择顺序,网格结果会有所不同,因为组是在无限结构中现有组之上构建的。
很好,但是现在我仍在寻找一种方法,可以使用rowSpan
属性在表格的单个单元格中正确显示网格分组数据。像这样:
单元格分组必须紧随组,然后按照分组后的顺序将分组后的数据连接在一起。
我一直困扰着这个单元格跨度问题,却没有找到一种合理的方式来渲染然后一起渲染。