如何为usercontrol编写适当的反应代码?

时间:2015-02-20 08:52:15

标签: javascript reactjs react-jsx

我正在使用reactJS构建“usercontrols”,并且渲染部件的方法看起来像这样:

var FeedTopic = React.createClass({
        render: function() {

            return (
                <div className="topic">
                    <div className="tUImgLnk">
                        <a title={this.props.data.UserName} target="_blank" href={this.props.data.UserInfoUrl}>
                            <img className="tUImg" src={this.props.data.UserPicSrc} />
                        </a>
                    </div>
                    <div className="tInfo">
                        <div className="tName">
                            <a title={this.props.data.UserName} target="_blank" href={this.props.data.UserInfoUrl}>{this.props.data.UserName}</a>
                        </div>
                        <div className="tTime">
                            <span>{this.props.data.DateCreated}</span>
                        </div>
                    </div>
                </div>
            );
        }
});

问题是我找不到一种容易隐藏/显示特定元素的简单方法。将if语句放在return中是行不通的。我可以这样写:

var GridRow = React.createClass({
        render: function() {
            var row;

            row = this.props.cells.map(function(cell, i) {
                if(cell.Data.CellType == 1){
                    if(cell.Data.Text1URL != null && cell.Data.Text1URL.length>0){
                        return <td className={cell.Meta.HTMLClass} key={i}><a target={cell.Data.URLTarget} href={cell.Data.Text1URL} title={cell.Data.Text1}>{cell.Data.Text1}</a></td>     
                    }
                    else {
                        return <td className={cell.Meta.HTMLClass} key={i}>{cell.Data.Text1}</td>
                    }

                }
                else if(cell.Data.CellType == 2){
                    if(cell.Data.IconUrl.length > 0){
                        return <td className={cell.Meta.HTMLClass} key={i}><a target={cell.Data.URLTarget} href={cell.Data.IconUrl} title={cell.Data.Text1}><img alt={cell.Data.Text1} title={cell.Data.Text1} src={cell.Data.IconSrc} /></a></td>
                    }
                    else{
                        return <td className={cell.Meta.HTMLClass} key={i}><img alt={cell.Data.Text1} title={cell.Data.Text1} src={cell.Data.IconSrc} /></td>
                    }
                }
                else if(cell.Data.CellType == 3){
                    return <td className={cell.Meta.HTMLClass} key={i}>
                                <a className={cell.Data.Text1Class} target={cell.Data.URLTarget} href={cell.Data.Text1URL} title={cell.Data.Text1}>
                                    {cell.Data.Text1}
                                </a><br/>
                                <a className={cell.Data.Text2Class} target={cell.Data.URLTarget} href={cell.Data.Text2URL} title={cell.Data.Text2}>
                                    {cell.Data.Text2}
                                </a>
                            </td>       
                }
                else if(cell.Data.CellType == 4){
                    return <td className={cell.Meta.HTMLClass} key={i}>
                                {cell.Data.Text1}<br/>
                                <a className={cell.Data.Text2Class} target={cell.Data.URLTarget} href={cell.Data.Text2URL} title={cell.Data.Text2}>
                                    {cell.Data.Text2}
                                </a>
                            </td>       
                }

            }.bind(this));

            return (
                <tr>
                    {row}
                </tr>
            );
        }
    });

但很难看出真正印刷的是什么markaup,它会涉及大量的repatativ标记。

我不确定为什么必须将它拆分为函数和返回。在ASP.NET MVC中编写它时,if语句在标记中正确,并且总是只有一个地方可以查找标记的打印方式。

在ASP.NET MVC中看起来像这样。

<div>
  <% if (contition) { %>
     <div class="MyProfile">
        ...
     </div>
  <% } %>
</div>

干净简洁

我这样做的方式是错误的,还是只是反应的方式?

1 个答案:

答案 0 :(得分:1)

  

我不确定为什么必须将它拆分为函数和返回。在ASP.NET MVC中编写它时,if语句在标记中正确,并且总是只有一个地方可以查找标记的打印方式。

这是因为您正在编写JavaScript代码,而不是将在以后解析和执行的模板。 JSX只是一种语法糖,它可以使嵌套标记/组件创建更好,而不是它转换为常规函数调用。

因此,在组织条件逻辑时,您需要打开编码帽。

对于相当简单的逻辑,嵌套{someArray.map()}调用并使用{someStatement && <contents>}{someStatement ? <contents> : <alt-contents>}条件可以帮助您完成大部分工作,但在这种情况下,您可以实际拥有一个开关和一些嵌套的条件很快就变丑了。

将每个不同的单元格类型渲染为每种类型的函数可能不那么难看。这些可以是独立的(因为它们不使用对this的任何引用,组件本身内的方法,甚至新GridRowCell组件中的方法,它们本身可以组织另一个组件的渲染基于单元格类型的实际渲染应该渲染得足够复杂,需要完全专业化。


这就是将渲染分解为同一组件中的不同方法可能如下所示:

var GridRow = React.createClass({
  render() {
    return <tr>
      {this.props.cells.map(function(cell, i) {
        return this['renderCellType' + cell.Data.CellType](cell, i)
      })}
    </tr>
  },

  renderCellType1(cell, i) {
    var contents = cell.Data.Text1
    if (cell.Data.Text1URL) {
      contents = <a target={cell.Data.URLTarget} href={cell.Data.Text1URL} title={cell.Data.Text1}>{contents}</a>
    }
    return <td className={cell.Meta.HTMLClass} key={i}>{contents}</td>     
  },

  renderCellType2(cell, i) {
    var contents = <img alt={cell.Data.Text1} title={cell.Data.Text1} src={cell.Data.IconSrc} />
    if (cell.Data.IconUrl) {
      contents = <a target={cell.Data.URLTarget} href={cell.Data.IconUrl} title={cell.Data.Text1}>{contents}</a>
    }
    return <td className={cell.Meta.HTMLClass} key={i}>{contents}</td>
  },

  renderCellType3(cell, i) {
    return <td className={cell.Meta.HTMLClass} key={i}>
      <a className={cell.Data.Text1Class} target={cell.Data.URLTarget} href={cell.Data.Text1URL} title={cell.Data.Text1}>
        {cell.Data.Text1}
      </a><br/>
      <a className={cell.Data.Text2Class} target={cell.Data.URLTarget} href={cell.Data.Text2URL} title={cell.Data.Text2}>
        {cell.Data.Text2}
      </a>
    </td>  
  },

  renderCellType4(cell, i) {
    return <td className={cell.Meta.HTMLClass} key={i}>
      {cell.Data.Text1}<br/>
      <a className={cell.Data.Text2Class} target={cell.Data.URLTarget} href={cell.Data.Text2URL} title={cell.Data.Text2}>
        {cell.Data.Text2}
      </a>
    </td>      
  }
});

这样做是为了感受逻辑,让我觉得渲染的网格行单元格由3个不同的部分组成 - 初始文本,链接文本,图标或链接图标以及始终相同的第二个链接,在应该显示第二个链接的情况下,它们之间有换行符。

如果你沿着这些线向下打破显示逻辑而不是按照单元格类型在顶层打破显示逻辑,则可能更容易关注/更少重复。


或仅在有嵌套条件逻辑的情况下内联条件和函数的混合:

var GridRow = React.createClass({
  render() {
    return <tr>
      {this.props.cells.map(function(cell, i) {
        var type = cell.Data.CellType
        var multiline = (type == 3 || type == 4)
        return <td className={cell.Meta.HTMLClass} key={i}>
          {type == 1 && this.renderCellType1(cell)}
          {type == 2 && this.renderCellType2(cell)}
          {type == 3 && <a className={cell.Data.Text1Class} target={cell.Data.URLTarget} href={cell.Data.Text1URL} title={cell.Data.Text1}>
              {cell.Data.Text1}
            </a>}
          {type == 4 &&  cell.Data.Text1}
          {multiline && <br/>}
          {multiline && <a className={cell.Data.Text2Class} target={cell.Data.URLTarget} href={cell.Data.Text2URL} title={cell.Data.Text2}>
            {cell.Data.Text2}
           </a>}
        </td>
      })}
    </tr>
  },

  renderCellType1(cell) {
    var contents = cell.Data.Text1
    if (cell.Data.Text1URL) {
      contents = <a target={cell.Data.URLTarget} href={cell.Data.Text1URL} title={cell.Data.Text1}>{contents}</a>
    }
    return contents   
  },

  renderCellType2(cell, i) {
    var contents = <img alt={cell.Data.Text1} title={cell.Data.Text1} src={cell.Data.IconSrc}/>
    if (cell.Data.IconUrl) {
      contents = <a target={cell.Data.URLTarget} href={cell.Data.IconUrl} title={cell.Data.Text1}>{contents}</a>
    }
    return contents
  }
})

或者引入一个新组件来使基本包装逻辑声明:

var Wrap = React.createClass({
  render() {
    if (!!this.props.when) {
      var {when, withTag, ...props} = this.props
      return <this.props.withTag {...props}>{this.props.children}</this.props.withTag>
    }
    else {
      return this.props.children
    }
  }
})

var GridRow = React.createClass({
  render() {
    return <tr>
      {this.props.cells.map(function(cell, i) {
        var type = cell.Data.CellType
        return <td className={cell.Meta.HTMLClass} key={i}>
          {type == 1 && <Wrap withTag="a" when={ccell.Data.Text1URL} target={cell.Data.URLTarget} href={cell.Data.Text1URL} title={cell.Data.Text1}>
            {cell.Data.Text1}
          </Wrap>}
          {type == 2 && <Wrap withTag="a" when={cell.Data.IconUrl} target={cell.Data.URLTarget} href={cell.Data.IconUrl} title={cell.Data.Text1}>
            <img alt={cell.Data.Text1} title={cell.Data.Text1} src={cell.Data.IconSrc}/>
          </Wrap>}
          {type == 3 && <a className={cell.Data.Text1Class} target={cell.Data.URLTarget} href={cell.Data.Text1URL} title={cell.Data.Text1}>
            {cell.Data.Text1}
          </a>}
          {type == 4 && cell.Data.Text1}
          {multiline && <br/>}
          {multiline && <a className={cell.Data.Text2Class} target={cell.Data.URLTarget} href={cell.Data.Text2URL} title={cell.Data.Text2}>
            {cell.Data.Text2}
           </a>}
        </td>
      })}
    </tr>
  }
})