在传统的HTML中,元素是构成页面的基础单元。但在React中构建页面的基础单元室React组件,可以在React组件中混入JavaScript表达能力的HTML元素。实际上写React代码主要就是构建组件,就像是编写文旦时使用元素一样。
本质上一个组件就是一个JavaScript函数,它接受属性(props)和状态(state)作为参数,并输出渲染好的HTML。组件一般被用阿里呈现和表单应用的某部分数据,因此可以把React组件理解成HTML元素的扩展。
一、扩展HTML
React+JSX是强大而富有表现力的工具,允许我们使用类似HTML语法创建自定义元素。比起单纯的HTML,他们还能控制生命周期中的行为,这些都是React.createClass方法开始的。
相较于集成,React偏爱复合(composition)即通过小巧的、简单的组件和数据对象,构建大而复杂的组件。
二、组件复合的例子:
一个渲染选择题的组件要满足以下几个条件:
接收一组选项作为输入。
把选项渲染给用户。
只允许用户选择一个选项。
HTML提供了一些基本的元素——单选类型的输入框和表单组(input group),可以在这里使用。组建的层级从上往下看是这样子的:
MutipleChoice 有一个 ReadioInput有一个 Input(type="radio")
以上就是组合模式(composition pattern)的特征。
三、组装HTML|
在React.DOM.input的命名空间域定义了input组件,因此我们要做的第一件事情是把它封装进一个RadioInput组件。这个组件负责定制原本通用的input,将其精缩成与单选按钮行为一致的组件。
先建立一个脚手架,其中包含所需要的渲染的方法和基本地的标记,用以描述想输出的界面。组合模式开始显现,组件变成了特定类型的输入框。
var AnswerRadioInput =React.createClass({
render : funciton(){
return(
<div className=“radio”>
<label>
<Input type="radio"/>
Label Text
</label>
</div>
);
}
});
四、添加动态属性
现在input还没有内容是动态的,所以下一步需要定义父元素必须传给单选框的那些属性。
这个输入框代表什么值或者选项?
用什么文本来描述它?
这个输入框的name是什么?
也许需要自定义id。
也许要重载它默认值。
有上述列表之后就可以定义一个input属性类型了,我们把这些添加到类的PropTypes对象中。
var AnwerRadioInput=React.createClass({
propTypes:{
id:React.PropTypes.string,
name:React.PropTypes.string.isRequired,
value:React.PropTypes.string.isRequired,
checked:React.Proptypes.bool
},
...
});
对于每个非必需的属性我们需要为其定义一个默认值。把他们添加到getDefaultProps方法当中。在每个新的实例当中,如果父组件没有提供它们数值,这些值就会被使用,由于这个方法只会在类上调用一次,而不是在每一个实例上都调用,因此不能再这里提供id——每个实例应该保持id的唯一性,这个问题可以用个接下来讲的(state)来解决。
var AnswerRadioInput =React.createClass({
propTypes:{...},
getDefaultProps:function(){
return{
id:null,
checked:false
};
},
});
五、追踪状态
我们的组件记录随时间变化而变化的数据。尤其对于每个实例来说都要求是唯一的id,以及用户可以随时更新的checked值。那我们来定义初始化状态。
var AnswerRadioInput =React.creteClass({
propTypes:{ ...},
getDefaultProps:function(){...},
getInitialState:function(){
var id=this.props.id?this.props.id:uniqueId('radio-')'
return{
checked: !!this.props.checked,
id:id,
name:id
};
},
});
六、整合到父组件当中
构建下一层——AnswerMultiplechoiceQuestion,这一层的主要作用是渲染一列选项让用户从中选择。按照上面介绍的模式,我们来创建这个组件基本的HTML和默认属性。
var AnswerMultipleChoiceQuestion=React.createClass({
proptypes:{
value:React.Proptypes.string,
choices:React.PropTypes.array.isRequired,
onCompleted:React.Proptypes.func.isrequired
},
getInitialState:function(){
return{
id:uniqueId('multiple-choice-'),
value:this.props.value
};
},
render:function(){
return(
<div classsName="form0group">
<label className ="survey-item-label"htmlFor={this.state.id}
</label>
<div className ="survey-item-content">
<AnswerRadioInput .../>
...
</AnswerRadioInput .../>
</div>
</div>
);
}
});
为了生成一列单选框子组件,我们需要对选项列表进行映射,把每一个选项转换为一个组件,这一点通过辅助函数很容易就处理好了