React的3种不同应用场景的组件渲染方式

19 September 2016

react 前后分离 数据直出 直出

前言

今天分享的是react在组件渲染这块的不同应用场景下的不同渲染方式的讲解。

页面数据区域html的渲染一般分为3种方式:

  • 1.前后分离–(这里说的是:接口返回数据)通过执行JS,发出请求并拿到数据
  • 2.数据直出– 数据请求在server端上提前获取,并和html一同返回
  • 3.直出– 数据请求在server端上提前获取,模板渲染也在server上完成,输出最终 HTML

1. 前后分离

这种模式的好处是能够使前后端开发完全分离,后端和前端只需要关注接口上数据的传输是否是对方需要的即可。

模式图如下: 前后分离

那么这种模式下,React里面这样获取数据,并且对页面进行渲染呢?

处理这个问题有2中方案,但效果会有一点差别:

  • 1.先渲染组件再获取数据
  • 2.先获取数据再渲染组件

1.1. 先渲染组件再获取数据

这里得先了解react知识点,即:react的原生方法 componentDidMount 。因为这个方案是先渲染组件再获取数据,所以数据请求这一步 是放到 componentDidMount里面的。

  getInitialState :  组件初始化
  componentWillMount : 组件挂载前执行
  componentDidMount : 组件挂载后执行

假设请求数据的方法如下:

   /**
  * [getCartData 获取购物车数据]
  * @return {[type]} [description]
  */ 
  function getCartData() {
    return  new Promise(function(resolve, reject) {
        setTimeout(function(){
            resolve([]);
        } , 3000);
    });   
  };

那么这种方式的代码实现如下:

  /**
   * [cart  购物车]
   */
  var Cart = React.createClass({
    getInitialState:function(){
        return {carts:[] , num : 0 , money: 0 ,isAll : false};
    },
    componentWillMount: function(){
        var carts = this.state.carts;
        var data = this.computed(carts);
        data.carts = carts;
        this.handleSet(data);
    },
    componentDidMount:function() {
        var that = this;
        getCartData().then(function(carts){
            that.setState({carts: carts});
            var data = that.computed(carts);
            data.carts = carts;
            that.handleSet(data);
        });
    },
    //...
    render: function(){
        return (<div>
                <CartItem carts={this.state.carts} onChange={this.handleChange} />
                <CartMenu isAll={this.state.isAll} isCheckAll={this.isCheckAll} num={this.state.num} money={this.state.money} onClick={this.handleClick} />
            </div>)
    }
  });

渲染组件的时候就无需从外部传人数据,数据要从state上获取。

 /**
 * [CART_INFO 渲染购物车]
 * @type {[type]}
 */
 ReactDOM.render(<Cart /> , document.getElementById('cart'));

1.2. 先获取数据再渲染组件

这种方式就好比ajax请求成功后执行success方法一样。react代码上与上一种方式就是去掉 componentDidMount方法。将这一步操作前移。并且componentWillMount 方法中的数据将不再是从内部的state获取,而是从props中获取。

code:

    /**
     * [cart  购物车]
     */
    var Cart = React.createClass({
      getInitialState:function(){
          return {carts:[] , num : 0 , money: 0 ,isAll : false};
      },
      componentWillMount: function(){
          var carts = this.props.carts;
          var data = this.computed(carts);
          data.carts = carts;
          this.handleSet(data);
      },
      //...
      render: function(){
          return (<div>
                  <CartItem carts={this.state.carts} onChange={this.handleChange} />
                  <CartMenu isAll={this.state.isAll} isCheckAll={this.isCheckAll} num={this.state.num} money={this.state.money} onClick={this.handleClick} />
              </div>)
      }
    });

接口返回再渲染组件。

  getCartData().then(function(carts){
         ReactDOM.render(<Cart carts={carts} /> , document.getElementById('cart'));
    });

1.3 比较

第一种组件内部只会在缺少数据的地方空白; 第二种组件还未渲染,所以会全部是一片空白。

1.4 DEMO

demo目录结构: 前后分离

https://github.com/Yi-love/koa-react-redux/tree/master/react

2.数据直出

很多同学都不知道数据直出是什么意思。其实很简单,就是用户打开某一个页面的时候,服务器在接受请求后,在渲染页面的时候顺带把数据也放到 页面中一起返回到前端(其实数据一般是放到了js变量里面)。

模式图如下: 数据直出

使用 Node 做服务器的情况下,koa作为web框架。服务器代码是非常简单的。

server代码:

数据直出

server html模版 和 react:

数据直出

DEMO

demo目录结构: 数据直出

https://github.com/Yi-love/koa-react-redux/tree/master/react-koa-webpack

3.直出(服务器渲染)

和react一直离不开的话题同构,一直困扰这我。直到我把react服务器渲染给弄出来了之后,我才明白同构大概的思路。那么服务器渲染在react中怎么使用呢。 首先Node必须让他支持jsx的编译,加上redux管理react的状态。

模式图如下: 直出

要了解这种模式就必须知道如下开发模式: 直出

服务器同样使用Nodekoa.

server代码: 直出

渲染出的react 模版如下: 直出

前端代码: 直出

1.4 DEMO

demo目录结构: 直出

https://github.com/Yi-love/koa-react-redux/tree/master/react-redux-koa-webpack