# React组件组合
组合本质上是对组件的一种组织、管理方式,实现代码的封装.
在传统HTML当中,html元素是构成页面的基本单元。但在React中,在React中构建页面的基本单元是React组件。整个React应用都是用组件组合来构建的。
本质上,一个组件就是一个Javascript函数,它接受属性(props)和状态(state)作为参数,并输出渲染好的HTML。组件一般被用来呈现和表达应用的某部分数据,因此你可以把React组件理解为HTML元素的扩展。
React推崇通过组合的方式来组织大规模的应用。
# 组件嵌套
在父组件中嵌套子组件和引用HTML标签一样:
<子组件名> ... </子组件名> //双标签
<子组件名 /> //单标签
所谓父子组件,就和DOM中的父子元素一样,他们是有从属关系
注意:render中return的HTML标签都必须有个最外层的标签包裹。
function Test (Props){
return (<div> 代码….. <div>); # 正确
return (<div>1</div><div>2</div>); # 错误
}
# 组件嵌套写法
# 正确写法
class Children extends React.Component{
render(){
return ( //有最外层的标签包裹
<div>i am from Children</div>
)
}
}
class Parent extends React.Component{
render(){
return ( //子组件必须包裹在一个HTML标签内
<div>
<Children fromParent={} />
</div>
)
}
}
# 错误写法
//错误1: 两个div没有包含在一个HTML标签内
class Children extends React.Component{
render(){
return (
<div>Others </div>
<div>i am from Children</div>
)
}
}
//错误2:子组件没有包含在一个HTML标签内
class Parent extends React.Component{
render(){
return(
<Children fromParent={} />
)
}
})
# 组件组合
接下来我们先通过一个留言板的示例为大家展示组件的组合使用。 留言板分为以下几个组件:
- CommentFrom 提交留言表单组件
- CommentList 留言展示列表组件
- CommentItem 一条留言组件
- CommentBox 留言组件
# 提交留言表单组件
留言板我们会有提交留言的表单组件,该组件我们叫做CommentFrom,我们在此处结合React部分约束表单来写该示例:
class CommentFrom extends React.Component{
constuctor(props){
super(props);
this.state = {
name:'',
val:''
}
}
render(){
return (<div>
<div>
<span>姓名:</span>
<input type="text" value={this.state.value} onChange={this.handleInputChange.bind(this)} />
</div>
<div>
<span>留言:</span>
<textarea value={this.state.val} onChange={this.handleTextareaChange.bind(this)}/>
</div>
<div>
<button onClick={this.handleSubmit.bind(this)}>提交</button>
</div>
</div>)
}
handleTextareaChange(e){
//在此处我们处理一下该数据,清除开始于结束的所有空格
var val = e.target.value.repalce(/^\s+|\s+$/,'');
this.setState({
val:val
})
}
handleInputChange(e){
this.setState({
name:e.target.value
})
}
handleSubmit(){
return {name:this.state.name,val:this.state.val};
}
}
# 留言展示列表组件
留言展示列表组件,在该组件中我们主要有2个组件,一个是单条留言组件,一个是留言列表组件。留言展示组件是由多个单条留言组成,在此处我们会初步进行一次组合使用。
//一条留言组件
class CommentItem extends React.Component{
render(){
return <div>
{/*姓名*/}
<span>{this.props.data.name}</span>
{/*留言内容*/}
<span>{this.props.data.val}</span>
</div>
}
}
//留言列表组件
class CommentList extends React.Component{
render(){
return (<div>
{/*在此处我们将一条留言组件在该组件中进行了组合,类似html的标签嵌套*/}
{this.props.list.map((item,index)=>{
<CommentItem data={item} key={index}/>
})}
</div>)
}
}
# 留言组件
留言组件就是一个容器组件,用来组合 提交留言表单组件 与 留言展示列表组件。
class CommentBox extends React.Component{
render(){
return (<div>
<CommentList/>
<CommentFrom/>
</div>)
}
}
//将该留言渲染到指定标签中
ReactDOM.render(<CommentBox/>,document.querySelector('#box'))
通过以上的例子,我们不难发现React组件组合其实与HTML标签的嵌套类似。在做开发的过程中,最重要的是拆分组件,往往拆分组件对于初次接触React的初学者而言是比较困难的,根据组件的目的来明确为什么要写该组件,组件的目的是为了复用,因此我们可以根据该思想来确定哪些组件需要拆分组合使用。
# 组件包含
通过上面留言板的例子,大家已经掌握了React的基本开发思想,为了更好的应用组件的组合,接下来,我们再介绍一个中更为巧妙的组合方式。
在我们开发组件过程中,往往我们不知道组件中的具体的内容是什么,只有在使用的时候才能明确其中的内容。例如: 在需求中,我们经常会用到Button按钮组件,但是有一些需求是组件中只需要出现文字,而有些需要出现图标与文字。
//注册按钮 只要文字
<Button>注册</Button>
//添加按钮需要添加图标结合文字
<Button><Icon type="add" />添加</Button>
//删除按钮只需要删除图标
<Button><Icon type="del"/></Button>
这种类型的组合类似我们有一个html标签,标签中的内容是在我们使用标签的时候去决定。这种类型的组件我们需要借助this.props.children属性来实现。
class Button extends React.Component{
render(){
return <button>{this.props.children}</button>
}
}
<Button>注册</Button> //当我们在Button组件中写入注册,那么对应的组件中this.props.children就是“注册”
<Button><Icon type="add" />添加</Button> //这种情况下 this.props.children 就是 <Icon type="add" />添加
我们完成一个面板组件(Panel),面板有标题,还有内容。但是内容我们不知道用户要放置什么,因此我们可以采用组件包含来完成该组件的设计。
class Panel extends React.Component{
render(){
return (<div className="panel">
<h3 className="panel-title">{this.props.title}</h3>
<div className="panel-body">
{this.props.children}
</div>
</div>);
}
}
//当前Panel中放置的内容为一个列表
<Panel title="用户列表">
<ul>
<li>张三</li>
<li>李四</li>
<li>王武</li>
</ul>
</Panel>
//当前panel中放置的内容为一段文本
<Panel title="激励的句子">
<p>不是因为看到希望而去做,是做了才有希望</p>
</Panel>