第一节我们看了antd的button源码,现在我们用class的常用写法改造下:
import React,{ Component } from "React";
var _classnames2 = require('classnames');
var rxTwoCNChar = /^[\u4e00-\u9fa5]{2}$/;
var isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar);
function isString(str) {
return typeof str === 'string';
}
var __rest = undefined && undefined.__rest || function (s, e) {
var t = {};
for (var p in s) {
if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
}
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0) t[p[i]] = s[p[i]];
}
return t;
};
class Button extends Component {
//初始化state
state = {
loading: this.props.loading
}
//构造函数
constructor(props) {
super(props);
[
'handleClick', 'handleMouseUp'
].forEach(func=> {
this[func] = this[func].bind(this);
});
}
//props的值发生变更时调用的方法
componentWillReceiveProps(nextProps) {
var _this2 = this;
var currentLoading = this.props.loading;
var loading = nextProps.loading;
if (currentLoading) {
clearTimeout(this.delayTimeout);
}
if (typeof loading !== 'boolean' && loading && loading.delay) {
this.delayTimeout = setTimeout(function () {
return _this2.setState({loading: loading});
}, loading.delay);
} else {
this.setState({loading: loading});
}
}
componentWillUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
if (this.delayTimeout) {
clearTimeout(this.delayTimeout);
}
}
handleClick(e){
// Add click effect
this.setState({clicked: true});
clearTimeout(this.timeout);
var _this=this;
this.timeout = setTimeout(function () {
return _this.setState({clicked: false});
}, 500);
var onClick = this.props.onClick;
if (onClick) {
onClick(e);
}
}
handleMouseUp(e){
if (this.props.onMouseUp) {
this.props.onMouseUp(e);
}
}
render() {
var _classNames;
//从props和state里获取相应的属性。
var _a = this.props,
type = _a.type,
shape = _a.shape,
_a$size = _a.size,
size = _a$size === undefined ? '' : _a$size,
className = _a.className,
htmlType = _a.htmlType,
children = _a.children,
icon = _a.icon,
prefixCls = _a.prefixCls,
ghost = _a.ghost,
others = __rest(_a, ["type", "shape", "size", "className", "htmlType", "children", "icon", "prefixCls", "ghost"]);
var _state = this.state,
loading = _state.loading,
clicked = _state.clicked;
// large => lg
// small => sm
var sizeCls = '';
switch (size) {
case 'large':
sizeCls = 'lg';
break;
case 'small':
sizeCls = 'sm';
default:
break;
}
function insertSpace(child, needInserted) {
// Check the child if is undefined or null.
if (child == null) {
return;
}
var SPACE = needInserted ? ' ' : '';
// strictNullChecks oops.
if (typeof child !== 'string' && typeof child !== 'number' && isString(child.type) && isTwoCNChar(child.props.children)) {
return React.cloneElement(child, {}, child.props.children.split('').join(SPACE));
}
if (typeof child === 'string') {
if (isTwoCNChar(child)) {
child = child.split('').join(SPACE);
}
return React.createElement(
'span',
null,
child
);
}
return child;
}
//定义_classNames 的相关属性
var iconType = 'loading';
var children = this.props.children;
var needInserted = React.Children.count(children) === 1 && !iconType;
var kids = React.Children.map(children, function (child) {
return insertSpace(child, needInserted);
});
var _classNames = {}
_classNames[prefixCls + '-' + type]=type;
_classNames[prefixCls + '-' + shape]=shape;
_classNames[prefixCls + '-' + sizeCls]=sizeCls;
_classNames[prefixCls + '-icon-only']= !children && icon && !loading;
_classNames[prefixCls + '-loading']=loading;
_classNames[prefixCls + '-clicked']=clicked;
_classNames[prefixCls + '-background-ghost']=ghost;
var classes = _classnames2(prefixCls, className,_classNames);
//创建相应的元素
return React.createElement(
'button',
{
type: htmlType || 'button',
className: classes,
onMouseUp: this.handleMouseUp,
onClick: this.handleClick
},
kids
);
}
}
//设置props的默认值
Button.defaultProps = {
prefixCls: 'ant-btn',
loading: false,
clicked: false,
ghost: false
};
//属性类型校验
Button.propTypes = {
type: React.PropTypes.string,
shape: React.PropTypes.oneOf(['circle', 'circle-outline']),
size: React.PropTypes.oneOf(['large', 'default', 'small']),
htmlType: React.PropTypes.oneOf(['submit', 'button', 'reset']),
onClick: React.PropTypes.func,
loading: React.PropTypes.oneOfType([React.PropTypes.bool, React.PropTypes.object]),
className: React.PropTypes.string,
icon: React.PropTypes.string
};
Button.__ANT_BUTTON = true;
export default Button;
其实就是把里面费劲的代码改成相应的常用代码而已,就基本能看懂了。
var Button = function (_React$Component) {
(0, _inherits3['default'])(Button, _React$Component);
其实为了实现继承React.Component
class Button extends Component {
看着这段代码,其实就是想给json设置值而已:
(0, _defineProperty3['default'])(_classNames, prefixCls + '-' + type, type),
(0, _defineProperty3['default'])(_classNames, prefixCls + '-' + shape, shape),
(0, _defineProperty3['default'])(_classNames, prefixCls + '-' + sizeCls, sizeCls),
(0, _defineProperty3['default'])(_classNames, prefixCls + '-icon-only', !children && icon && !loading),
(0, _defineProperty3['default'])(_classNames, prefixCls + '-loading', loading),
(0, _defineProperty3['default'])(_classNames, prefixCls + '-clicked', clicked),
(0, _defineProperty3['default'])(_classNames, prefixCls + '-background-ghost', ghost),
_classNames[prefixCls + '-' + type]=type;
_classNames[prefixCls + '-' + shape]=shape;
_classNames[prefixCls + '-' + sizeCls]=sizeCls;
_classNames[prefixCls + '-icon-only']= !children && icon && !loading;
_classNames[prefixCls + '-loading']=loading;
_classNames[prefixCls + '-clicked']=clicked;
_classNames[prefixCls + '-background-ghost']=ghost;
state默认值设置:
_this.state = {
loading: props.loading
};
也就对应了下面代码
state = {
loading: this.props.loading
}
还有就是
(0, _createClass3['default'])(Button, [
{
key: 'componentWillReceiveProps',
....
这个就不用解释了,其实就是定义了相应的函数而已。