javascript - 需要迭代数组的方向

标签 javascript reactjs

请原谅我的无知。我刚刚开始使用 React,我确信我在这里遗漏了一些非常简单的东西。因此,根据我从 loadData 返回的数据量,我需要在 1 2 或 3 列中显示数据。我正在使用 ul 和 li。我根据屏幕大小计算一列可以容纳多少个。我尝试将它们全部放在一个 ul 中,但我需要在顶部有一个标题行,所以我真的需要最多 3 个 ul,第一个 li 具有标题信息。我如何循环并创建我需要的 uls 数量?我试着在返回周围放一个循环,但我做不到。非常感谢任何帮助。

    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 是否正确。这是我的 nee 渲染:

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>
    );
}

最佳答案

通过使用 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将是一个数组数组,它​​将您的数据映射到您建议的 View 结构。具体来说,你的 ul s 将由 uls 中的每个数组表示;然后,嵌套数组中的每个项目将代表一个 li . 取uls[0]作为你的第一个ululs[0][0]将是你的第一个li你的第一个ul .

_.take可以找到文档 here

_.chunk可以找到文档 here

希望,将您的数据转换为与您想要的 View 类似的结构将有助于插入您前进。

我还要说代码还有很多其他问题。例如,React 人员可能会告诉您混合使用 jQuery 是一种禁忌。

更新 2017 年 9 月 15 日 我仔细考虑了一下,意识到有一种没有双重迭代的更冗长的方法。你想要的不超过三列,我们可以用它来映射出三个单独的 ul所有元素都包含要显示的全部项目的 block 。如果该 block 碰巧不存在(项目少于最大值 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

还有其他可以改进的地方。

  1. 代替 var colC = _.map(_.nth(chunks, 2), item => <li>{item}</li>) , 创建另一个类会更干净,也许是ListItemli代替。 所以, var colC = _.map(_.nth(chunks, 2), item => <ListItem data={item} />)
  2. 奇怪的是,我注意到列表项的部分列从上到下排列。所以如果你'abcedfghijkl'.split('')你会得到两列,第二组 li位于底部。我不太清楚为什么,但我觉得它并没有影响演示。

关于 React 的最后说明,以及我不/不会使用它的原因。它的许可证并不是真正开放的,许多人对此表示担忧。如果您刚刚接触 React,现在可能是选择其他东西的好时机。参见 this reddit

关于javascript - 需要迭代数组的方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46230839/

相关文章:

javascript - 将数组添加到javascript中的对象数组

javascript - 我可以在单个播放器中添加多个 VAST 标签吗?意思是,如果一个巨大的广告加载失败,则采用另一个广告

javascript - 如何获取 Parsley.js 的语言环境

javascript - 使用 Material UI 菜单时在控制台中收到警告。建议我解决方案。我在文本对象中使用 HTML

javascript - 如何防止相同的组件在导航时重新渲染? react 路由器 v6

javascript - 如何让 Greasemonkey 重定向到本地资源?

javascript - 将结果显示为输入文本

javascript - 没有 sibling 时不考虑跨度填充,但在有 sibling 时保留

css - 如何改变 Ant 设计 Tooltip 的宽度

javascript - 尝试遍历 React 中的多个组件