React 組件開發入門

er74 9年前發布 | 24K 次閱讀 React 移動Web開發框架 移動開發

 

前言

熟悉 React 的思想后,我們先來嘗試開發一個單純的小組件,可以對比一下是不是比以前的開發模式更加舒適了,這里我主要以一個 Loadding 組件來舉栗子,實現了幾個基本的功能:

  • 一種類型的 loadding(菊花轉)
  • 能夠設置 loadding 的三個屬性:width height color
  • 能夠控制 loadding 的顯示和隱藏
  • </ul>

    其實對于一個簡單需求來說,這三個屬性已經很實用了。但是去網上看一些外國大神寫的組件,有一些不明白的地方,所以自己就慢慢搞,do it!

    設計

    我想這樣用 loadding 組件:

    React 組件開發入門

    所以我定義這個組件的基本結構如下:

    var Loadding = React.createClass({
      // 控制組件屬性的類型
      propTypes: {},
      // 控制組件屬性的默認值
      getDefaultProps: function () {},
      // 組裝基本的內聯樣式
      getComponentStyle: function () {},
      // 渲染基本的組件,拆分 render 方法的粒度
      renderBaseComp: function () {},
      // 最終的渲染方法
      render: function () {}
    });

    這個組件中,我使用的 內聯樣式 來控制組件的內部基本樣式的穩定。其實有時候我們會覺得內聯樣式不好,但是我個人覺得每一種設置 CSS 形式的方法,用在合適的場景中就是正確的。

    每部分的具體實現如下,代碼中有一些講解(這里我不會介紹具體 loadding 效果是怎么出來的,看代碼應該就會明白,主要介紹一個 react 制作簡單組件的思路和寫法)對于擴展性來說,

    你還可以加入 className 和 type 這些修飾性的屬性,但是我更傾向于迭代式的組件開發,小組件就要具有良好的封閉性,使用接口簡單,大組件才考慮更好的魯棒性和可擴展性,這樣開發一個組件 的性價比才高。需要注意對 getDefaultProps 的理解,只有當使用接口的人代碼中根本沒有寫那個屬性的時候,才會使用定義的默認值。

    </div>

    實現

    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;
    }

     本文由用戶 er74 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
     轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
     本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!