使用JSX定义React组件:组件定义、动态值、子节点

 2016年01月22日    1156     声明


React推荐将每一个业务点都建立一个独立的组件,并将所有逻辑和标签封装在其中,创建组件使用React.createClass()方法。JSX以干净简洁的方式保证了组件中的标签与所有业务逻辑的分离,它不仅提供了清晰、直观的方式来描述组件树,同时也让应用程序更加符合逻辑。


  1. 定义一个组件
  2. 组件使用动态值
  3. 子节点与组件复合


1. 定义一个组件

现在,我们要定义一个分页组件,期望输出如下HTML:

<div className="divider">
  <h2>Questions</h2><hr/>
</div>

要创建一个上面HTML为内容的React组件,我们使用createClass()进行包装,并使用render方法渲染到页面:

var App = React.createClass({
  render: function () {
    return (
      <div className="divider">
        <h2>Questions</h2><hr/>
      </div>
    )
  }
});

ReactDOM.render(
  React.createElement(App),
  document.getElementById('example')
);

组件制作完成,现在已经可以渲染到页面上了。但只能静态显示,为了让其更实用, 接下来我们会将h2标签中的内容动态显示。

完整代码请查看:divider.html


2. 组件使用动态值

JSX语法会将花括号{…}之间的内容渲染为动态值。花括号指向了一个JavaScript上下文环境,任何放入花括号之间的内容都会进行求值,结果会被渲染为标签中的若干子节点。

花括号之间的内容,可是一个JavaScript变量名、函数、表达式。

2.1 使用变量名

使用变量名动态显示组件内容时可以像下面这样:

var text = 'Questions';
<h2>{text}</h2>

//<h2>Questions</h2>

完整代码请查看:dynamicValue-variable.html


2.2 使用数组

当变量是一个数组时,React会对将数组中的每个元素渲染为一个节点:

var text = ['Hello', 'world'];
<h2>{text}</h2>

//Helloworld

数组渲染后HTML如下:

<div class="divider" data-reactid=".0">
  <h2 data-reactid=".0.0">
    <span data-reactid=".0.0.0">Hello</span>
    <span data-reactid=".0.0.1">world</span>
  </h2>
  <hr data-reactid=".0.1">
</div>

完整代码请查看:dynamicValue-variable.html


2.3 使用函数

对于更复杂的逻辑,我们可以将其封装成一个函数,并在花括号中调用这个函数:

function dateToString(d) {
  return [
    d.getFullYear(),
    d.getMonth()+1,
    d.getDate()
  ].join('-');
}

<h2>{dateToString(new Date())}</h2>

// 2016-1-23

从上面示例可以看出,花括号之间可以是任何有效的JavaScript表示式,大家可自行尝试更多用法。完整代码请查看:dynamicValue-function.html


3. 子节点与组件复合

比起显示这些简单值,我们会希望沉渲染一些更复杂的数据,如,把数组中的数据分别渲染为若干个 h2。这时我们就需要使用子节点。


3.1 使用子节点

在前面的示例中,使用createClass()创建组件后,又使用render()将其渲染到了DOM(虚拟DOM)中。渲染到React DOM中的是一个ReactElement,而我们使用JSX语法时,JSX可以自动将其转换成一个ReactElement。因此,我们也可以像下面这样渲染组件:

ReactDOM.render(
  <App></App>,
  document.getElementById('example')
);

React对组件中花括号内的动态值的处理,会将其渲染成若干个组件。因此,我们可以通过定义组件的子节点属性来显示动态值:

var App = React.createClass({
  render: function () {
    return (
      <div className="divider">
        <h2>{this.props.children}</h2><hr/>
      </div>
    )
  }
});

ReactDOM.render(
  <App>itiblu.com</App>,
  document.getElementById('example')
);

//<h2>itiblu.com</h2>

与HTML标签不同,JSX中组件要以大写字母开头。在上面示例中,我们在<App>标签之间插入了动态值,也就是子节点,而在组件中通过this.props.children属性引用子节点。可以看出,这种方式比使用JavaScript表示式更为简单易用。完整代码请查看:child.html


3.2 组件的复合

很多时候,子组件并不是一个,而是一个动态列表,这样我们就需要动态的创建子组件,并将其复合到父组件中。

我们可以像下面这样定义子组件,并实现的组件的复合:

var LiItem = React.createClass({
render: function() {
  return <li>{this.props.data.name}</li>;
}
});
var App = React.createClass({
render: function () {
  return (
  <ul>
    {this.props.results.map(function(result){
      return <LiItem key={result.id} data={result} />;
    })}
  </ul>
  )
}
});

var results = [
{id:'itbilu.com', name:'IT笔录'},
{id:'yijiebuyi.com', name:'一介布衣'},
{id:'niefengjun.cn', name:'老聂'}
];
ReactDOM.render(
<App results={results} />,
document.getElementById('example')
);

以上示例代码输出如下:

<ul data-reactid=".0">
  <li data-reactid=".0.$itbilu=1com">IT笔录</li>
  <li data-reactid=".0.$yijiebuyi=1com">一介布衣</li>
  <li data-reactid=".0.$niefengjun=1cn">老聂</li>
</ul>

与HTML属性类似,JSX语法中也定义了props,你可以像HTML属必一样将JSX属性传递到子组件中。完整代码请查看:child-dynamic.html

本文示例代码,请查看:demo2