如何“覆盖”渲染功能?

时间:2015-06-12 11:16:50

标签: reactjs

我刚刚开始使用React。我有一个包含许多表的项目,有些非常复杂,但通常都会从一组数据中输出一个表。一些具有父子关系(具有可切换的子行),并且每个具有稍微不同的行输出格式(例如,一些具有打开模态的按钮)。通常情况下,我会使用jQuery DataTables,这对于这样的事情来说很容易和灵活。不过,我正在努力弄清楚如何在React中可持续地(可扩展?)。

我编写了一个基本的表组件,它通过props接受一组项目并吐出一个表并通过内部状态处理子行。今天我将它转换为使用两个组件:表和行的单独组件。我真的不想写X或2X不同的组件(其中X是项目中的表的数量),但我不知道如何使它可重用。所有表都应该有一些共同点,如样式,过滤器功能,分页等,我会尝试将其放在Table组件级别并重用。

到目前为止,我考虑过的最佳解决方案是通过props传递preRender函数并使用它来创建实际的行JSX,并使render函数只汇编所有那些片段分成一个输出(这基本上就是我已经用Array.map做的了。然后我可以通过一个道具(如果有效)提供preRender,如下所示:

var Table = React.createClass({
    render: function() { // mixin?
        var rows = [];
        for (var i=0; i<this.props.items.length; i++) {
            rows.push(this.props.preRender(this.props.items[i]));
        }
        return rows; // plus html boilerplate...
    }
});

var Parent = React.createClass({
    render: function() {
        var foodItems = this.state.foodItems;
        var drinkItems = this.state.drinkItems;
        var foodRender = function(i) { return (<tr>{i} <a href?>Buy me</a></tr>); }
        var drinkRender = function(i) { return (<tr>{i} <button>Drink me</button></tr>); }

        return (
            <Table items={foodItems} preRender={foodRender}/>
            <Table items={drinkItems} preRender={drinkRender}/>
        );
    }
});

我想到的另一件事是以某种方式将不同的Row组件传递给Table组件,如果可能的话。我猜根本问题是:

  1. 表格级别的内容在各个表格中非常相似或相同,但可能部分需要每个表进行自定义。
  2. 做事情就像打开的弹出窗口一样,所以他们会有一个状态(或需要围绕w / props)。
  3. 有没有更好的方法来进行这种逻辑/依赖注入,或者我可能只需要制作大量略有不同的控件。

1 个答案:

答案 0 :(得分:2)

我从这样的事情开始(为简洁起见使用ES6语法):

const FoodItem = React.createClass({
  render() {
    return (
      <tr><td>{this.props.item} <a href="something">Buy me</a></td></tr>
    );
  }
});


const DrinkItem = React.createClass({
  render() {
    return (
      <tr><td>{this.props.item} <button>Drink me</button></td></tr>
    );
  }
});


const Table = React.createClass({
  render() {
     const {items, itemComponent: ItemComponent} = this.props;

     return (
       <table>
         {items.map(item => <ItemComponent item={item} />)}
       </table>  
     );
   }
});


const Parent = React.createClass({
  render() {
    return (
      <div>
        <Table items={this.state.foodItems} itemComponent={FoodItem}/>
        <Table items={this.state.drinkItems} itemComponent={DrinkItem}/>
      </div>
    );
  }
});

另一种模式(最好取决于您的要求):

const FoodItem = React.createClass({
  render() {
    return (
      <tr><td>{this.props.item} <a href="something">Buy me</a></td></tr>
    );
  }
});


const DrinkItem = React.createClass({
  render() {
    return (
      <tr><td>{this.props.item} <button>Drink me</button></td></tr>
    );
  }
});


const Table = React.createClass({
  render() {   
     // I'm assuming you ultimately want your table to do something cleverer than just rendering a table element
     return (
       <table>{this.props.children}</table>  
     );
   }
});


const Parent = React.createClass({
  render() {
    return (
      <div>
        <Table>{this.state.foodItems.map(item => <FoodItem item={item} />)}</Table>
        <Table>{this.state.drinkItems.map(item => <DrinkItem item={item} />)}</Table>
      </div>
    );
  }
});