官术网_书友最值得收藏!

Multiple components

"Shawn, let's get back to our application. We are using almost the same code from last time but you can set up a new JSBin. We have included the latest React library and bootstrap library in the HTML tab. We have also added a container element, which we will render our React app."

<!DOCTYPE html>
<html>
  <head>
    <script src="https://code.jquery.com/jquery.min.js"></script>
    <link  rel="stylesheet" type="text/css" />
    <script src="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
    <script src="http://fb.me/react-with-addons-0.14.3.js"></script>
    <script src="http://fb.me/react-dom-0.14.3.js"></script>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>JSX in Detail</title>
  </head>
  <body>
    <p id="container">
    </p>
  </body>
</html>

"Right now, we are only using a single component to display the data from the recent changes API."

var App = React.createClass({
  render: function(){
    var headings = this.props.headings.map(function(heading) {
      return(<th>
        {heading}
      </th>);
    });

    var rows = this.props.data.map(function(row){
      return  <tr>
        <td>{row.when}</td>
        <td>{row.who}</td>
        <td>{row.description}</td>
      </tr>

    })
      return <p><h1>{this.props.title}</h1><table>
        <thead>
          {headings}
        </thead>
        {rows}
      </table></p>
  }
});

"Let's split this single component into small composable components. These simple modular components will use other modular components with well-defined self-contained interfaces."

"Got it" said Shawn.

"Ok. The first step is trying to identify the different components that are present in our single component."

"Currently, our render method lists tableHeadings and tableRows as the children of table element."

return(<table>
             {tableHeadings}
             {tableRows}
       </table>);

"I guess we will make the components for the headings and rows?" Shawn asked.

"Yes. But we can go one step further. Both headings and rows are lists of still smaller units, a Heading and a Row tag, respectively. It can be visualized as follows:"

<table>
  <Headings>
    <Heading/>
    <Heading/>
  </Headings>
  <Rows >
    <Row/>
    <Row/>
  </Rows>
</table>

"Makes sense, Mike. Let me try to create Heading now."

"Sure, go ahead."

var Heading = React.createClass({
  render: function() {
    return(<th>{heading}</th>);
  }
});

"Mike, I think this will work, except the heading. I am not sure how to render the actual heading in the <th> tag."

"Don't worry about it. Let's just assume that it will be passed as props to the Heading component."

"Sure. Here is the Heading component then:"

var Heading = React.createClass({
  render: function() {
    return(<th>{this.props.heading}</th>);
  }
}); 

"Perfect! The Row component will also be similar to Heading. It will get the changeSet object in its props"

var Row = React.createClass({
  render: function() {
    return(<tr>
             <td>{this.props.changeSet.when}</td>
             <td>{this.props.changeSet.who}</td>
             <td>{this.props.changeSet.description}</td>
          </tr>);
  }
});

"Shawn, we are done with lowest-level components. Now, it's time to move up a level. Let's build Headings first."

"Similar to how a Heading component will get its title in props, Headings will get a list of titles passed to it."

var Headings = React.createClass({
  render: function() {
    var headings = this.props.headings.map(function(heading) {
      return(<Heading heading = {heading}/>);
    });

   return (<thead><tr>{headings}</tr><thead>);
  }
});

"We are iterating over the list of titles and converting them into a list of the Heading components. The Headings component is controlling how the props are passed to the inpidual Heading components. In a sense, inpidual Heading components are owned by Headings." explained Mike.

"In React, an owner is the component that sets props of other components. We can also say that if the X component is present in the render() method of the Y component, then Y owns X." Mike further added.

"Shawn, go ahead and build the Rows component similar to Headings."

"Here you go:"

var Rows = React.createClass({
  render: function() {
    var rows = this.props.changeSets.map(function(changeSet) {
      return(<Row changeSet = {changeSet}/>);
    });
    return ({rows});
  }
});

"There is just one issue. You can't render the rows as it's a collection of components. Remember that the render() function can only render one tag" Mike said.

"I guess I should wrap the rows in a <tbody> tag.", Shawn."

var Rows = React.createClass({
  render: function() {
    var rows = this.props.changeSets.map(function(changeSet) {
      return(<Row changeSet = {changeSet}/>);
    });

    return (<tobdy>{rows}</tbody>);
  }
});

"Perfect. We have almost everything now. Let's finish it by adding the top-level App component."

var App = React.createClass({
  render: function(){
    return <table className = 'table'>
             <Headings headings = {this.props.headings} />
             <Rows changeSets = {this.props.changeSets} />
           </table>;
    }
});

"Here's how our complete code looks now:"

var Heading = React.createClass({
  render: function() {
    return <th>{this.props.heading}</th>;
  }
});

var Headings = React.createClass({
  render: function() {
    var headings = this.props.headings.map(function(name) {
      return <Heading heading = {name}/>;
    });
   return <thead><tr>{headings}</tr></thead>;
  }
});

var Row = React.createClass({
  render: function() {
    return <tr>
             <td>{this.props.changeSet.when}</td>
             <td>{this.props.changeSet.who}</td>
             <td>{this.props.changeSet.description}</td>
           </tr>;
  }
});

var Rows = React.createClass({
  render: function() {
    var rows = this.props.changeSets.map(function(changeSet) {
      return(<Row changeSet = {changeSet}/>);
    });
    return <tbody>{rows}</tbody>;
  }
});


var App = React.createClass({
  render: function() {
    return <table className = 'table'>
             <Headings headings = {this.props.headings} />
             <Rows changeSets = {this.props.changeSets} />
           </table>;
    }
});

var data = [{ "when": "2 minutes ago",
              "who": "Jill Dupre",
              "description": "Created new account"
            },
            {      
              "when": "1 hour ago",
              "who": "Lose White",
              "description": "Added fist chapter"
           }];
var headings = ['When', 'Who', 'Description'];

ReactDOM.render(<App headings = {headings} 
                     changeSets = {data} />, 
                                      document.getElementById('container')); 

"Shawn, I think you have understood the power of composability of components now. It makes our UI easy to reason with and easy to reuse and compose. We will be using this philosophy throughout with React."

"I agree. Every component does one thing right and in the end, all of them get composed together so that the whole application is built. Different parts of the code get separated in such a way that they don't interfere with each other."

主站蜘蛛池模板: 万荣县| 丽江市| 海淀区| 德庆县| 石台县| 乐清市| 锡林郭勒盟| 鞍山市| 波密县| 孟津县| 昌邑市| 玉环县| 肥东县| 营山县| 镇赉县| 刚察县| 兴仁县| 竹山县| 弋阳县| 张家界市| 桦川县| 阳朔县| 邯郸县| 新野县| 庆阳市| 沧源| 蓬莱市| 清镇市| 余干县| 八宿县| 穆棱市| 安化县| 玉林市| 荔波县| 潞城市| 临海市| 东阳市| 屯门区| 南开区| 稻城县| 云霄县|