React 組件開發入門

前言

熟悉 React 的思想後,咱們先來嘗試開發一個單純的小組件,能夠對比一下是否是比之前的開發模式更加溫馨了,這裏我主要以一個 Loadding 組件來舉栗子,實現了幾個基本的功能:react

  • 一種類型的 loadding(菊花轉)
  • 可以設置 loadding 的三個屬性:width height color
  • 可以控制 loadding 的顯示和隱藏

其實對於一個簡單需求來講,這三個屬性已經很實用了。可是去網上看一些外國大神寫的組件,有一些不明白的地方,因此本身就慢慢搞,do it!web

設計

我想這樣用 loadding 組件:動畫

使用代碼

因此我定義這個組件的基本結構以下:this

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

這個組件中,我使用的 內聯樣式 來控制組件的內部基本樣式的穩定。其實有時候咱們會以爲內聯樣式很差,可是我我的以爲每一種設置 CSS 形式的方法,用在合適的場景中就是正確的。spa

每部分的具體實現以下,代碼中有一些講解(這裏我不會介紹具體 loadding 效果是怎麼出來的,看代碼應該就會明白,主要介紹一個 react 製做簡單組件的思路和寫法)對於擴展性來講,.net

你還能夠加入 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(不考慮不支持的狀況,不支持都不用開發,直接用圖,性價比更高)code

[@include](https://my.oschina.net/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](https://my.oschina.net/extend) .top;
		}
		[@for](https://my.oschina.net/362326) $i from 1 through 4 {
			&:nth-child(#{$i}) {
				transform:rotate(45deg * ($i - 1));
				.top {
					[@include](https://my.oschina.net/include) animation(load, 0.8s, linear, 0s, infinite);
				}
				.bottom {
					[@include](https://my.oschina.net/include) animation(load, 0.8s, linear, 0.4s + $i/10, infinite);
				}
			}
		}
	}
}

裏面用到的一個 animation 混淆方法:orm

@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;
}
相關文章
相關標籤/搜索