请原谅我的无知。我刚开始使用反应,我相信我在这里错过了一些非常简单的东西。因此,根据我从loadData返回的数据量,我需要在1 2或3列中显示数据。我正在使用ul和li。我根据屏幕大小计算出可以容纳多少列。我尝试将它们全部放在一个ul中,但我需要在顶部有一个标题行,所以我真的需要最多3 uls,第一个li有头信息。我如何循环并创建我需要的数量?我尝试围绕回归做了一个循环,但我无法做到。非常感谢任何帮助。
var appointmentBoardSection = React.createClass({
displayName: "appointmentBoardSection",
getInitialState: function() {
return {
key: null,
results: [],
parameters: this.props.parameters,
type: "",
};
},
shouldComponentUpdate: function(nextProps, nextState) {
console.info("this.state.key: " + this.state.key);
console.info("nextState.key: " + nextState.key);
if (this.state.key !== nextState.key) {
console.info("NO MATCH!!!!");
//this.forceUpdate();
return true;
}
return false;
},
componentDidMount: function() {
console.info("MOUNTED!!!");
var _this = this;
_this.loadData();
setInterval(function() {
_this.loadData();
}, 10000);
},
loadData: function() {
console.info("LOADING DATA....");
var _this = this;
$.when(_api.callPromise('apiRouter.ashx', 'getAppointmentsBoard', JSON.stringify(masterPage.reporting.parameters), this.props.type)).then(function(data) {
var totalData = data.args[0];
if (totalData.length <= 0) {
$("div#" + _this.props.type).hide();
} else {
$("#no_data").hide();
$("div#" + _this.props.type).show();
}
_this.setState({
results: totalData,
key: Math.random()
});
masterPage.hidePleaseWait(true);
});
},
render: function() {
var contHeight = $(window).height();
var offsetTop = $("div.appt_bd_container").offset().top;
var realEstate = contHeight - 400;
var perColumn = Math.round(realEstate / 70);
console.info("height: " + $(window).height());
console.info("offsetTop: " + offsetTop);
console.info("perColumn: " + perColumn);
var maxICanShow = perColumn * 3;
var limitResults = false;
var colCount = 3;
var colDef = "";
var colWidth = 100;
var numberOfColsNeeded = Math.round(this.state.results.length / perColumn);
if (numberOfColsNeeded > 3) {
colCount = 3;
} else {
colCount = numberOfColsNeeded;
}
switch (colCount) {
case 2:
colWidth = 50;
break;
case 3:
colWidth = 33.333;
break;
default:
colDef = "";
colWidth = 100;
}
if (this.state.results.length > maxICanShow) {
var i = 1;
console.info("this.state.results.length: " + this.state.results.length);
console.info("maxICanShow: " + maxICanShow);
while (i < this.state.results.length - (maxICanShow - 1)) {
this.state.results.pop();
i++;
}
}
var curColData = [];
var overallCount = this.state.results.length;
var testArr = [];
for (var i = 0; i < colCount; i++) {
testArr.push({});
}
if (this.state.results.length > perColumn) {
for (var i = 0; i < perColumn; i++) {
if (overallCount > 0) {
curColData.push(this.state.results.shift());
overallCount--;
}
}
}
var myTest = [];
return ( <
ul className = "appt_bd" >
<
li className = "appt_bd_header"
style = {
{
width: colWidth + '%'
}
} >
<
span className = "appt_bd_header_main" > {
this.props.title
} < /span> <
span className = "appt_bd_header_sub" > Appts Set < /span> <
span className = "appt_bd_header_sub" > Appts Show < /span> <
/li> {
curColData.map(function(row) {
return <AppointmentBoardRow colWidth = {
colWidth
}
key = {
row.userId
}
row = {
row
}
/>;
})
} <
/ul>
);
}
});
var AppointmentBoardRow = React.createClass({
render: function() {
var row = this.props.row;
return ( <
li className = "appt_bd_row"
style = {
{
width: this.props.colWidth + '%'
}
}
key = {
row.userId
} >
<
span className = "appt_bd_desc" >
<
span className = "appt_bd_rank" > {
row.rank
} < /span> <
span className = "appt_bd_avatar_container" > < div className = {
row.className
} > < span className = "initials" > {
row.initials
} < /span></div > < /span> <
span className = "appt_bd_user" >
<
span className = "appt_bd_description_main" > {
row.userName
} < /span> <
span className = "appt_bd_description_sub" > {
row.role
} < /span> <
/span> <
/span> <
span className = "appt_bd_data" >
<
span className = "appt_bd_data_main" > {
row.apptsSetCount
} < /span> <
span className = "appt_bd_data_sub" > /{row.apptsSetGoal}</span >
<
/span> <
span className = "appt_bd_data" >
<
span className = "appt_bd_data_main" > {
row.apptsShowCount
} < /span> <
span className = "appt_bd_data_sub" > /{row.apptsShowGoal}</span >
<
/span> <
/li>
);
}
});
****编辑回应Josh ...我现在遇到的一个问题是什么都没有显示虽然我可以验证uls是否正确。这是我的渲染:
render: function () {
var contHeight = $(window).height();
var offsetTop = $("div.appt_bd_container").offset().top;
var realEstate = contHeight - 400;
var perColumn = Math.round(realEstate / 70);
var maxICanShow = perColumn * 3;
var colWidth = 100;
var uls = _.chunk(_.take(this.state.results, maxICanShow), perColumn);
let li = "";
return (
<div>
{uls.map((lis) => {
<ul className="appt_bd">
<li className="appt_bd_header" style={{ width: colWidth + '%' }}>
<span className="appt_bd_header_main">{this.props.title}</span>
<span className="appt_bd_header_sub">Appts Set</span>
<span className="appt_bd_header_sub">Appts Show</span>
</li>
lis.map(li => {<li className="appt_bd_row" style={{ width: this.props.colWidth + '%' }} key={li.userId}>
<span className="appt_bd_desc">
<span className="appt_bd_rank">{li.rank}</span>
<span className="appt_bd_avatar_container"><div className={li.className}><span className="initials">{li.initials}</span></div></span>
<span className="appt_bd_user">
<span className="appt_bd_description_main">{li.userName}</span>
<span className="appt_bd_description_sub">{li.role}</span>
</span>
</span>
<span className="appt_bd_data">
<span className="appt_bd_data_main">{li.apptsSetCount}</span>
<span className="appt_bd_data_sub">/{li.apptsSetGoal}</span>
</span>
<span className="appt_bd_data">
<span className="appt_bd_data_main">{li.apptsShowCount}</span>
<span className="appt_bd_data_sub">/{li.apptsShowGoal}</span>
</span>
</li>})
</ul>
})}
</div>
);
}
答案 0 :(得分:2)
通过使用lodash,您可以简化构建布局的算法。请参阅下文,了解render
render: function() {
var contHeight = $(window).height();
var offsetTop = $("div.appt_bd_container").offset().top;
var realEstate = contHeight - 400;
var perColumn = Math.round(realEstate / 70);
var maxICanShow = perColumn * 3;
var uls = _.chunk(_.take(this.state.results, maxICanShow), perColumn);
switch (uls.length) {
case 2:
colWidth = 50;
break;
case 3:
colWidth = 33.333;
break;
default:
colDef = "";
colWidth = 100;
}
在此之后,您不需要您编写的任何其他代码,直到
return {...
但您需要将模板映射到uls
而不是curColData
。它看起来像这样(过于简化):
uls.map((lis) => {
<ul>
<li> my header </li>
lis.map(li => <li></li>)
</ul>
})
值得注意的是,我的解决方案在return
视图中使用了双重迭代,在可能的情况下应该避免 - 特别是在可能很大的集合中;但由于你的集合不会(给定容器的大小)并且你想动态构建嵌套元素,它似乎是需求的正确模式。
现在uls
将是一个数组数组,用于将数据映射到您建议的视图结构。具体来说,您的ul
将由uls
中的每个数组表示;那么,嵌套数组中的每个项目都代表li
。
将uls[0]
作为您的第一个ul
,uls[0][0]
将成为您第一个li
的第一个ul
。
_.take
文档here
_.chunk
文档here
希望将您的数据转换为与所需视图类似的结构将有助于您前进。
我还要说代码中还有许多其他问题。例如,React人员可能会告诉你混合jQuery是一个禁忌。
更新9/15/17
我想到了更多,并意识到没有双重迭代有更冗长的方式。您只需要三列,我们可以使用它来映射三个单独的ul
元素,这些元素都包含要显示的总项目的块。如果该块恰好不存在(项目数量少于max this.state.results.length < maxICanShow
),那么由于方便的花花公子lodash,它不会成为问题。请参阅以下代码:
class ListPane extends React.Component {
render () {
var contHeight = 900;//$(window).height();
var offsetTop = 50; //$("div.appt_bd_container").offset().top;
var realEstate = contHeight - 400;
var perColumn = Math.round(realEstate / 70);
var maxICanShow = perColumn * 3;
var uls = "abcedefhijklmnopqrstuvwxyz".split("");
var chunks = _.chunk(_.take(uls, maxICanShow), perColumn);
var colWidth = 0;
var colA = _.map(_.nth(chunks, 0), item => <li>{item}</li>)
var colB = _.map(_.nth(chunks, 1), item => <li>{item}</li>)
var colC = _.map(_.nth(chunks, 2), item => <li>{item}</li>)
const listItems = chunks.map((lis) =>
<ul>
<li> {lis} </li>
</ul>
);
switch (chunks.length) {
case 2:
colWidth = 50;
break;
case 3:
colWidth = 33.333;
break;
default:
colWidth = 100;
}
return (
<div>
<ul>
{colA}
</ul>
<ul>
{colB}
</ul>
<ul>
{colC}
</ul>
</div>
)
}
}
注意我使用_.nth
来保护代码免受潜在的null
或不可解析的引用。
另外,请查看此codepen
还可以进行其他改进。
var colC = _.map(_.nth(chunks, 2), item => <li>{item}</li>)
,
在ListItem
替代创建另一个类可能更加清晰,可能li
。
所以,
var colC = _.map(_.nth(chunks, 2), item => <ListItem data={item} />)
'abcedfghijkl'.split('')
,您将获得两列,第二组li
位于底部。我不是很确定为什么,但不觉得它从演示中消失了。关于React的最终说明,以及为什么我不会/不会使用它。它的许可证并非真正开放,许多人都对此感到担忧。如果您刚刚进入React,可能是选择其他东西的好时机。见this reddit