不需要渲染组件时的最佳实践

时间:2015-09-01 13:49:52

标签: javascript reactjs

我在React中有点新鲜,所以我的问题是关于我试图做的事情的最佳实践。我可能不会"思考反应"所以我需要你的帮助。

我参与了一个与体育相关的非常大的项目。为了尽量减少我需要创建的组件数量,我尝试使用一个组件来处理多项运动。

我将尝试绘制一个基本场景,它将与我尝试做的类似事情相匹配。

-----------------------------------
|  module: Scoreboard             |
|                                 |
|  -----------------------------  |
|  | module: scores            |  |
|  |   Sydney 1 x 0 Melbourne  |  |
|  -----------------------------  |
|                                 |
|  -----------------------------  |
|  | module: results           |  |
|  -----------------------------  |
|                                 |
|  -----------------------------  |
|  | module: Footer            |  |
|  -----------------------------  |
|                                 |
-----------------------------------

考虑到这种情况,请注意在加载组件时或通过父组件加载所有道具。

我需要在我的脚本上做两件事。

1 - 如果有一个由this.props.footer表示的页脚,则仅显示组件页脚 2 - 如果存在由this.props.results表示的结果,则仅显示组件结果

现在我有一些用户案例,我可以在这里做。

用户案例(父母控制)

在我的 渲染 方法中,我可以做一些事情(不要介意{... this.props}我只是在那里代表我&# 39; m传递变量)

案例1:

render: function() {
    var results, footer;

    if (this.props.results) {
        results = (<results {...this.props} />)
    }

    if (this.props.footer) {
        results = (<footer {...this.props} />)
    }

    return (
       <div class="scoreboard">
           <scores {...this.props} />
           {results}
           {footer}
       </div>
    );
}

我在这里看到的缺点是渲染中的ifs数量。不太可读,特别是如果我们有两个以上的组件做同样的事情

案例2:

render: function() {
    return (
       <div class="scoreboard">
           <scores {...this.props} />
           {this.props.results ? <results {...this.props} /> : ''}
           {this.props.footer ? <footer {...this.props} /> : ''}
       </div>
    );
}

虽然我更喜欢这种情况,但有时我的组件需要大量的属性才能解决上述相同的问题(可读性)。请记住,我使用{... this.props}来简化示例

用户案例(儿童控制)

我更喜欢这种情况。把所有逻辑放在它自己的组件中。

问题是我不知道如何停止第一次渲染。而且我也不想放一个&#34;显示:block&#34;在页面上避免在不需要的地方添加不必要的标记,所以我的想法是,如果不需要,我根本不会渲染组件。 如果我做错了,或者这是一个反模式,我想对它有一些见解,就像我说的,我对所有这些反应都很新,任何评论都是受欢迎的。

所以基本上,就像我说的那样,我无法阻止渲染。

让我们以结果组件为例,让我们有一个表,其中大约有10行标记。我们来一个案例:

在我的 渲染 方法中,我可以执行类似

的操作
module: SCOREBOARD 

render: function() {
    return (
       <div class="scoreboard">
           <scores {...this.props} />
           <results {...this.props} isVisible={this.props.results} />
           <footer {...this.props} isVisible={this.props.footer}  />
       </div>
    );
}

module: RESULTS

render: function() {
    return this.props.isVisible ? (
       <div class="results">
             <table>
                ....
             </table>
       </div>
    ) : null;
}

我将使用属性isVisible控制渲染的返回。默认它总是假的。 Haven没有找到关于它的好文章,但我认为这不是一种优雅的方式。

我知道我们有一个shouldComponentUpdate,但这不会停止页面上的第一个渲染,这将在我们的示例中显示一些表。

我想知道是否有人有一些见解,一个有效的论据或解决方案来做我想做的事情。请记住,它是一个很大的项目,所以我试图避免创建数百个组件,而是必须使用一个组件,其中有一些变量,我可以或不在页面上显示组件。 / p>

4 个答案:

答案 0 :(得分:5)

如果你有这个:

render: function() {
    return (
       <div class="scoreboard">
           <scores {...this.props} />
           {this.props.results ? <results {...this.props} /> : ''}
           {this.props.footer ? <footer {...this.props} /> : ''}
       </div>
    );
}

您可以将其重写为不同的方法:

render: function() {
    return (
       <div class="scoreboard">
           <scores {...this.props} />
           {this.props.results ? this.renderResults() : ''}
           {this.props.footer ? this.renderFooter() : ''}
       </div>
    );
},
renderResults(){
    return (
        <results {...this.props} />
    );
},
renderFooter(){
    return (
        <footer {...this.props} />
    );
},

这样条件部分永远不会随着更多道具变大,但是 你仍然可以用完整的东西进行子渲染。

  

为了尽量减少我需要创建的组件数量,我尝试使用一个组件来处理多项运动

拥有很多组件并不是很糟糕。你可以拥有很多微小的组件。在决定边界时考虑这些(根据明天要求的变化)。

对于兄弟姐妹(具有类似api但未嵌套的多个组件):

  • 我是否需要一次更新这些组件?合并
    • 示例:主要按钮是您想要更改一次并使其影响所有内容的
  • 我需要在这些组件之间有区别吗?分裂
    • 示例:记分板可能有显着的显示差异

对于父母/子女:

  • 分裂使测试更容易吗?分裂
    • 例子。输入列表,一个输入的测试事件比测试输入列表更简单
  • 是否通过拆分降低了复杂性?分割
  • 分裂结果是毫无意义的微小组件吗?合并
  

避免添加不必要的标记

有不必要的标记是经常在反应中发生的事情。这是一种权衡,但通常不会引起问题。

  

我将使用属性isVisible

控制渲染的返回

这是一种反模式。除非您在每个组件中执行此操作,否则您将对组件的用户进行假设,这会使您的代码更少模块化并且更难以维护。在父母中进行条件渲染,除非你有充分的理由不这样做。

答案 1 :(得分:0)

我是这样做的;

    module: RESULTS

    render: function() {
        if (this.props.hide) return null;
        return (
             <div class="results">
                         <table>
                                ....
                         </table>
             </div>
        );
    }

它是清晰度和性能的良好模式。

答案 2 :(得分:0)

如果您想要做的唯一事情不是显示,页脚和结果在可见时,请选择解决方案。即使解决方案2较短,解决方案一仍然是更好的可读性,

似乎你正在寻找一种方法,删除if语句,以便减少代码,尽管你可以在解决方案三中看到,它只会导致代码复杂性。

我不知道你传递给页脚/结果的其他道具,但对于这个特定情况,if语句是最好的方法。

    [shouldComponentUpdate]
    Invoked before rendering when new props or state are being received. This method is not called for the initial render or when forceUpdate is used. (facebook docs)

-U可以使用它来例如在旧的和新的道具之间进行(浅)比较,并返回 true,何时渲染,而不渲染时为false(但这只会在更新时触发), 它必须首先具有旧值(如你所描述的)

    [componentWillReceiveProps]
    invoked when a component is receiving new props. This method is not called for the initial render.
    Use this as an opportunity to react to a prop transition before render() is called by updating the state using this.setState(). The old props can be accessed via this.props. Calling this.setState() within this function will not trigger an additional render. (facebook)

-U可以做一些魔法,当组件接收道具时,你可以决定这样做 this.setState({isVisible:false});然后在你的渲染中检查isVisible:false,并且不显示其内容,然后更新此状态。但是,你不想拥有&#34;陈述&#34;生活在你的组件中

您也可以将支柱传递给组件,组件visible = {false}和 然后在子组件中检查this.props.visible,但是你只是移动了if语句

但这不是它应该工作的方式,单向数据流的概念(自上而下) 响应生命周期是从上面触发更改,你不应该停止渲染, 如果将props传递给它的子组件,它应该重新呈现 - &gt;如果你想停止渲染,你应该只在数据没有改变的情况下在shouldcomponent更新中进行,(看看不可变的js(和purerender)),

但是对于这种情况,只需使用if语句。

我还建议您查看更高级别的组件, http://browniefed.com/blog/2015/05/02/react/(也读取mixis已死,其中包含长篇作文链接)

答案 3 :(得分:0)

React文档has a whole page on conditional rendering。如果您正在寻找最佳实践,我会从那里开始。对于短线和单线元素,我个人喜欢using the logical && operator的简洁性。它看起来很像你的案例2:

render: function() {
    return (
       <div class="scoreboard">
           <scores {...this.props} />
           {this.props.results && <results {...this.props} />}
           {this.props.footer && <footer {...this.props} />}
       </div>
    );
}