构造复合型组件

上篇文章中,已使用组件技术,实现了一个“五彩冰粉”的网页控件。 从中可以体会到,组件其实就是把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控件的事件响应机制,未完待续 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章