1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// 这部分代码写的很乱
import React, { Component, PureComponent } from 'react';
// 这个山炮怎么又换了一种命名?
import setClass from 'classnames';
import PropTypes from 'prop-types';
// 这个函数会创建一个新的对象,然后把你出想去除的属性从对象中删除
// var object = { 'a': 1, 'b': '2', 'c': 3 };
// _.omit(object, ['a', 'c']);
// => { 'b': '2' }
import omit from 'lodash/omit';

const BLACK_LIST = [
'type',
'size',
'htmlType',
'block',
'component',
'disabled',
'loading',
'outline',
'bordered',
'className',
'prefix'
];

// 为啥要这么写?有毒吧?
const BTN_BLACK_LIST = ['href', 'target'].concat(BLACK_LIST);

const A_BLACK_LIST = ['href', 'target'].concat(BLACK_LIST);

export default class Button extends (PureComponent || Component) {
static propTypes = {
type: PropTypes.oneOf(['default', 'primary', 'success', 'danger', 'link']),
size: PropTypes.oneOf(['large', 'medium', 'small']),
htmlType: PropTypes.oneOf(['button', 'submit', 'reset']),
className: PropTypes.string,
block: PropTypes.bool,
component: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
disabled: PropTypes.bool,
loading: PropTypes.bool,
outline: PropTypes.bool,
bordered: PropTypes.bool,
prefix: PropTypes.string
};

static defaultProps = {
type: 'default', // 风格 'default' 'primary' 、 'danger' 、 'success'
size: 'medium', // 尺寸 'medium' 'large' 、 'small'
htmlType: 'button', // button标签原生type属性 'button' submit 、 reset 、 button
className: '', // 自定义类名
block: false,
disabled: false, // 状态控制 false
loading: false, // 状态控制
outline: false, // 边框有颜色,内部没有颜色
bordered: true, // 边框透明控制
prefix: 'zent'
};

constructor(props) {
super(props);
}

// 处理点击事件
handleClick = (event) => {
if (this.props.disabled || this.props.loading) return;

if (this.props.onClick) {
this.props.onClick(event);
}
}

// render a 标签
renderLink = (classNames) => {
// 如果没有 自定义组件标签类型 就是 a 标签
const Node = this.props.component || 'a';
// loading 和 disabled 都会禁用掉按钮
const disabled = this.props.disabled || this.props.loading;
const { href = '', target } = this.props;
const nodeProps = omit(this.props, A_BLACK_LIST);

return (
<Node
{...(disabled ? {} : { href, target })}
{...nodeProps}
className={classNames}
onClick={this.handleClick}
>
{this.props.children}
</Node>
);
}

// render button 标签
renderButton = (classNames) => {
const Node = this.props.component || 'button';
const disabled = this.props.disabled || this.props.loading;
const htmlType = this.props.htmlType;
const nodeProps = omit(this.props, BTN_BLACK_LIST);

return (
<Node
{...nodeProps}
{...(htmlType ? { type: htmlType } : {})}
className={classNames}
disabled={disabled}
onClick={this.handleClick}
>
{this.props.children}
</Node>
);
}

render() {
// 如果传进来了 href/target ,按钮就变成了链接
let renderer =
(this.props.href || this.props.target) ? 'renderLink' : 'renderButton';

let {
className,
type,
size,
block,
disabled,
loading,
outline,
bordered,
prefix
} = this.props;
let classNames = setClass(
{
[`${prefix}-btn-${type}${outline ? '-outline' : ''}`]:
type !== 'default',
[`${prefix}-btn-${size}`]: size !== 'medium',
[`${prefix}-btn-block`]: block,
[`${prefix}-btn-loading`]: loading,
[`${prefix}-btn-disabled`]: disabled,
[`${prefix}-btn-border-transparent`]: !bordered
},
`${prefix}-btn`,
className
);

return this[renderer](classNames);
}
}