在array.map

时间:2015-12-22 17:28:19

标签: javascript reactjs

我创建了一个用React.js动态加载其内容的网页。我从REST api调用中检索对象数组,然后将它们提供给表。我遇到的问题是array.map中的onClick赋值不会触发指定的函数。

我认为这是[ ]上下文问题,但我不确定如何解决它。 array.map中的[ this ]与array.map之外的[ ]不同如console.log所示。

我创建了两个独立的html文件进行演示。第一个包含静态创建的对象,该对象正确调用onClick函数:

https://jsfiddle.net/m1vugyd9/

第二次尝试从一组对象动态加载,但不起作用:

https://jsfiddle.net/avmbdxte/

我不知道这些链接有多长时间处于活动状态,所以如果它们不起作用,我还会在下面包含实际的html。差异在评论中略显突出。

静态 - 工作:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <style>
        table {
            text-align: center;
        }
    </style>
</head>
<body>
    <div id="reactDiv"></div>

    <script src="https://fb.me/react-0.14.3.min.js"></script>
    <script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
    <script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
    <script type="text/jsx">
        var FMap = React.createClass({
            render: function() {
                return (
                    <tr>
                        <td>{this.props.sTable}</td>
                        <td>{this.props.sField}</td>
                        <td>{this.props.dTable}</td>
                        <td>{this.props.dField}</td>
                        <td><a href="#" onClick={this.props.mapCountClick}>{this.props.mapCount}</a></td>
                    </tr>
                );
            }
        });

        var Main = React.createClass({

            getInitialState: function () {
                return { mapData: [] };
            },

            editMaps: function() {
                alert("Clicked on map editor");
            },

            render: function () {
                var maps = [
                    {
                        mapID: 1,
                        sourceT: "sT1",
                        sourceF: "sF1",
                        destT: "dT1",
                        destF: "dF1",
                        mapCount: 6
                    },
                    {
                        mapID: 2,
                        sourceT: "sT1",
                        sourceF: "sF2",
                        destT: "dT1",
                        destF: "dF2",
                        mapCount: 2
                    }
                ];



                /////////////////////////////////////////////////////
                // this is the static part that's different from the dynamic part
                var fMaps =
                    <FMap key="1"
                          sTable="sT1"
                          sField="sF1"
                          dTable="dT1"
                          dField="dF1"
                          mapCount="6"
                          mapCountClick={this.editMaps} />;
                // end of difference
                /////////////////////////////////////////////////////



                return (
                    <table width="100%">
                        <thead>
                            <tr>
                                <th>SourceT</th>
                                <th>SourceF</th>
                                <th>DestT</th>
                                <th>DestF</th>
                                <th>MapCount</th>
                            </tr>
                        </thead>
                        <tbody>
                            {fMaps}
                        </tbody>
                    </table>
                );
            }
        });

        React.render(<Main />, document.getElementById("reactDiv"));
    </script>
</body>
</html>

动态 - 不起作用:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <style>
        table {
            text-align: center;
        }
    </style>
</head>
<body>
    <div id="reactDiv"></div>

    <script src="https://fb.me/react-0.14.3.min.js"></script>
    <script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
    <script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
    <script type="text/jsx">
        var FMap = React.createClass({
            render: function() {
                return (
                    <tr>
                        <td>{this.props.sTable}</td>
                        <td>{this.props.sField}</td>
                        <td>{this.props.dTable}</td>
                        <td>{this.props.dField}</td>
                        <td><a href="#" onClick={this.props.mapCountClick}>{this.props.mapCount}</a></td>
                    </tr>
                );
            }
        });

        var Main = React.createClass({

            getInitialState: function () {
                return { mapData: [] };
            },

            editMaps: function() {
                alert("Clicked on map editor");
            },

            render: function () {
                var maps = [
                    {
                        mapID: 1,
                        sourceT: "sT1",
                        sourceF: "sF1",
                        destT: "dT1",
                        destF: "dF1",
                        mapCount: 6
                    },
                    {
                        mapID: 2,
                        sourceT: "sT1",
                        sourceF: "sF2",
                        destT: "dT1",
                        destF: "dF2",
                        mapCount: 2
                    }
                ];



                /////////////////////////////////////////////////////
                // this is the part that doesn't work
                var fMaps = maps.map(function (map) {
                    var component = this;

                    return (
                        <FMap key={map.mapID}
                            sTable={map.sourceT}
                            sField={map.sourceF}
                            dTable={map.destT}
                            dField={map.destF}
                            mapCount={map.mapCount}
                            mapCountClick={this.editMaps} />
                    );
                });
                // end
                /////////////////////////////////////////////////////



                return (
                    <table width="100%">
                        <thead>
                            <tr>
                                <th>SourceT</th>
                                <th>SourceF</th>
                                <th>DestT</th>
                                <th>DestF</th>
                                <th>MapCount</th>
                            </tr>
                        </thead>
                        <tbody>
                            {fMaps}
                        </tbody>
                    </table>
                );
            }
        });

        React.render(<Main />, document.getElementById("reactDiv"));
    </script>
</body>
</html>

工作示例(感谢pvg!):

https://jsfiddle.net/qLp9uuq3/

另一个工作示例(感谢Matthew Herbst!):

https://jsfiddle.net/09n6xss2/

1 个答案:

答案 0 :(得分:7)

在代码的动态部分:Map()默认情况下不会从组件中获取this的值,因此您需要绑定它:

var fMaps = maps.map(function (map) {
  return (
    <FMap key={map.mapID}
      sTable={map.sourceT}
      sField={map.sourceF}
      dTable={map.destT}
      dField={map.destF}
      mapCount={map.mapCount}
      mapCountClick={this.editMaps} />
  );
}.bind(this));

如果您使用了ES6箭头功能,this将被词汇继承,您就不会遇到此问题:

var fMaps = maps.map((map) => {
  return (
    <FMap key={map.mapID}
      sTable={map.sourceT}
      sField={map.sourceF}
      dTable={map.destT}
      dField={map.destF}
      mapCount={map.mapCount}
      mapCountClick={this.editMaps} />
  );
});

考虑到您可能已经使用Babel或其他工具进行JSX转换,可能也值得研究ES6转换。开始学习未来的好方法!