上篇文章中,已使用组件技术,实现了一个“五彩冰粉”的网页控件。 从中可以体会到,组件其实就是把html, javascript, 和css 以有机的方式结合在一起,形成一个高度可重用的独立单元
本篇文章中,将研究组件的另一特性,就是它的组合性,React组件 技术的一大杀伤力在于,它能让我们通过把微小简单的组件结合起来,进而创造出复杂强大的复合组件,
把控件分解成 若干个简单的控件,然后把这些简单小控件组合起来,最终形成我 们想要的页面组件,调色板控件如图,在
文本框中输入颜色的数值,点击 回车,文本框上面的小版块就会改变成文本框中输入的数值相一致 的颜色
我们可以把这个控件分成两部分,一部分是上面用于显示颜色的 小方块,我们可以称之为显色板,另一部分就是下边的文本输入框 。
于是,要完成这个控件,我们需要完成三个步骤:
1, 创建一个控件,用于实现显色板
2, 创建一个控件,用于实现文本输入框
3, 将两个控件有机结合起来
在代码中创建三个组件,第1个组件用来构建显色板,我们把它 命名为square,
第2个组件对应的是文本输入框,我们把它命名为 label,
第三个组件作用是把前两个组件整合起来,形成我们最终 想要的控件。代码如下:
<script type="text/babel">
var destination = document.querySelector("#container");
var Square = React.createClass({
render:function() {
return (
<p>This is a square</p>
);
}
});
var Label = React.createClass({
render:function() {
return (
<p>This is a label</p>
);
}
});
var Card = React.createClass({
render: function() {
var cardStyle = {
height:200,
width:150,
padding:0,
backgroundColor:"#FFF",
WebkitFilter:"drop-shadow(0px 0px 5px #666)",
filter: "drop-shadow(0px 0px 5px #666)"
};
return (
<div style={cardStyle}>
<Square/>
<Label/>
</div>
)
}
})
ReactDOM.render(
<div>
<Card/>
</div>,
destination
);
</script>
上篇文章提到过,React在设计控件样式时,可以把原来css的 设计属性转变为js的json对象,与控件的业务逻辑放到一起。 这里我们需要注意一个属性叫WebkitFilter, 该属性与我们以前 提到的命名机制不一样,我们以前说,属性的命名要采取骆驼格式 ,也就是首单词小写,第二个大小,依次类推,但这里,该属性 首个单词就大写了,这是因为这个属性是专门针对webkit内核的 浏览器的,所以,当某个属性是针对某个具体厂商开发的浏览器 时,该属性第1个单词的首字母要大写。
接下来,处理控件上面的显色板部分,同理我们先定义显色板 的显示样式,添加代码如下:
var Square = React.createClass({
render:function() {
var squareStyle ={
height:150,
backgroundColor:"#FF6663"
}
return (
<div style={squareStyle}>
<p>This is a square</p>
</div>
);
}
});
继续完善下面的文本框 输入控件:
var Label = React.createClass({
render:function() {
var labelStyle = {
fontFamily:"sans-serif",
fontWeight:"bold",
padding:13,
margin:0
};
return (
<p style={labelStyle}>#FF6663</p>
);
}
});
完成以上代码后,整个控件的基本样式已经成型,接下来我们把 精力集中到控件的业务逻辑上
现在,控件有一个问题,就是上面显色板显示的颜色和下面文本框显示的字符,是在代码里写死的,最后要完成的控件 ,其功能是让用户输入颜色,然后显色板根据用户输入改变它该 显示的颜色。解决这个问题的办法,那就是 依赖控件的属性机制。
当前控件需要动态可变的有两部分,一部分上显色板的背景色,该 颜色需要根据用户的输入进行相应变动,另一部分是下面文本框的 输入内容。因此我们需要做的改变是将这两部分的属性设置由原来 的写死转变为从外部通过属性传递进来,因此代码做如下改变:
var Square = React.createClass({
render:function() {
var squareStyle = {
height:150,
backgroundColor: this.props.color
}
return (
<div style={squareStyle}>
<p>This is a square</p>
</div>
);
}
});
var Label = React.createClass({
render:function() {
var labelStyle = {
fontFamily:"sans-serif",
fontWeight: "bold",
padding:13,
margin: 0
};
return (
<p style={labelStyle}>{this.props.color}</p>
);
}
});
由于这两个控件间套在父控件Card的内部,因此用户如果想要把 信息传递给它们,那么信息需要先传递给父控件Card,然后通过父控件Card再次传递给这两个子控件,因此代码修改如下:
var Card = React.createClass({
render:function() {
var cardStyle = {
height: 200,
width: 150,
padding: 0,
backgroundColor: "#FFF",
WebkitFilter:"drop-shadow(0px 0px 5px #666)",
filter: "drop-shadow (0px 0px 5px #666)"
};
return (
<div style={cardStyle}>
<Square color={this.props.color
<Label color={this.props.color
</div>
);
}
});
ReactDOM.render(
<div>
<Card color="#FF6663"/>
</div>,
destination
);
加载修改的代码后,我们可以看到显色板的颜色和下面文本框的文本已经改变了
总结:
本节,我们我们注重的是组件的组合特性,也就是一个复杂的组件可以通过多个简单的小组件组合而成。此篇文章先观察一个最终组件是怎样的,然后倒推回去,把整个大组件分割成两个小组件的结合。
把大组件分割成小组件,分别实现每个小组件后,接下来的问题是 如何把零散的小组件组合起来,把小组件作为大组件的子控件 ,把他们间套在大控件所对应的标签中。同时需要注意到,内部控件的属性想要获得外部输入进行, 需要先把属性值提交给父控件,然后再由父控件把获得的信息转移 给它内部的子控件,内部子控件是不能直接获取外部信息的。
当前控件存在一个问题是,下面文本框不能接收收户输入, 要解决这个问题,需要研究React控件的事件响应机制,未完待续