转载

React 组件开发入门

前言

熟悉 React 的思想后,我们先来尝试开发一个单纯的小组件,可以对比一下是不是比以前的开发模式更加舒适了,这里我主要以一个 Loadding 组件来举栗子,实现了几个基本的功能:

  • 一种类型的 loadding(菊花转)
  • 能够设置 loadding 的三个属性:width height color
  • 能够控制 loadding 的显示和隐藏

其实对于一个简单需求来说,这三个属性已经很实用了。但是去网上看一些外国大神写的组件,有一些不明白的地方,所以自己就慢慢搞,do it!

设计

我想这样用 loadding 组件:

React 组件开发入门

所以我定义这个组件的基本结构如下:

var Loadding = React.createClass({  // 控制组件属性的类型  propTypes: {},  // 控制组件属性的默认值  getDefaultProps: function () {},  // 组装基本的内联样式  getComponentStyle: function () {},  // 渲染基本的组件,拆分 render 方法的粒度  renderBaseComp: function () {},  // 最终的渲染方法  render: function () {} });  

这个组件中,我使用的 内联样式 来控制组件的内部基本样式的稳定。其实有时候我们会觉得内联样式不好,但是我个人觉得每一种设置 CSS 形式的方法,用在合适的场景中就是正确的。

每部分的具体实现如下,代码中有一些讲解(这里我不会介绍具体 loadding 效果是怎么出来的,看代码应该就会明白,主要介绍一个 react 制作简单组件的思路和写法)对于扩展性来说,

你还可以加入 className 和 type 这些修饰性的属性,但是我更倾向于迭代式的组件开发,小组件就要具有良好的封闭性,使用接口简单,大组件才考虑更好的鲁棒性和可扩展性,这样开发一个组件的性价比才高。需要注意对 getDefaultProps 的理解,只有当使用接口的人代码中根本没有写那个属性的时候,才会使用定义的默认值。

实现

var Loadding = React.createClass({  propTypes: {   width: React.PropTypes.oneOfType([    React.PropTypes.number,    React.PropTypes.string   ]),   height: React.PropTypes.oneOfType([    React.PropTypes.number,    React.PropTypes.string   ]),   color: React.PropTypes.string,   active: React.PropTypes.bool  },  getDefaultProps: function() {   return {    color: '#00be9c',    height: 30,    width: 30,    active: false   };  },  getComponentStyle: function() {   var width = this.props.width,    height = this.props.height,    color = this.props.color;   /* 中间圆心 */   var cWidth = 0.4 * width,    cHeight = 0.4 * height,    cMarginLeft = -0.5 * cWidth,    cMarginTop = -0.5 * cHeight;   /* 基本样式 */   return {    loaddingStyle: { // loadding 容器     width: width,     height: height    },    lineStyle: { // loadding 元件样式     background: color    },    centerStyle: { // loadding 圆心样式     width: cWidth,     height: cHeight,     marginLeft: cMarginLeft,     marginTop: cMarginTop    }   };  },  renderBaseComp: function(compStyle) {   /* 生成动画元件 */   var n = 4; // 元件个数,todo: 定制个数   var lines = []; // 元件元素集合   for (var i = 0; i < n; i++) {    lines.push(     <div className="line">      <span className="top" style={ compStyle.lineStyle }></span>      <span className="bottom" style={ compStyle.lineStyle }></span>     </div>    );   }   return lines;  },  render: function() {   /* 生成组件自己的样式 */   var compStyle = this.getComponentStyle();   /* 模拟渲染基本动画元件 */   var lines = this.renderBaseComp(compStyle);   // loadding 的class,控制交互   var loaddingClasses = cx({    loadding: true,    active: this.props.active   });   return (    <div className={ loaddingClasses } style={ compStyle.loaddingStyle }>     {lines}     <div className="loadding-center" style={ compStyle.centerStyle }></div>    </div>   );  } });  

最后,下面是基本的 SASS(不考虑不支持的情况,不支持都不用开发,直接用图,性价比更高)

@include keyframes(load) {  0% {   opacity: 0;  }  25% {   opacity: .25;  }  50% {   opacity: .5;  }  75% {   opacity: .75;  }  100% {   opacity: 1;  } } .loadding {  display: none;  position: absolute;  &.active {   display: block;  }  .loadding-center {   position: absolute;   left: 0;   top: 50%;   background: #fff;   border-radius: 50%;  }  .line {   position: absolute;   top: 0;   left: 0;   height: 100%;   .top {    content: '';    display: block;    width: 1px;    font-size: 0;    height: 50%;   }   .bottom {    @extend .top;   }   @for $i from 1 through 4 {    &:nth-child(#{$i}) {     transform:rotate(45deg * ($i - 1));     .top {      @include animation(load, 0.8s, linear, 0s, infinite);     }     .bottom {      @include animation(load, 0.8s, linear, 0.4s + $i/10, infinite);     }    }   }  } }  

里面用到的一个 animation 混淆方法:

@mixin keyframes($name) {  @-webkit-keyframes #{$name} {   @content;  }  @-moz-keyframes #{$name} {   @content;  }  @-ms-keyframes #{$name} {   @content;  }  @keyframes #{$name} {   @content;  } } @mixin animation ($name, $duration, $func, $delay, $count, $direction: normal) {  -webkit-animation: $name $duration $func $delay $count $direction;  -moz-animation: $name $duration $func $delay $count $direction;  -o-animation: $name $duration $func $delay $count $direction;  animation: $name $duration $func $delay $count $direction; }  
正文到此结束
Loading...