Skip to content

Commit e811172

Browse files
author
luoxin
committed
1.0.1 加入Object.assign,修复value BUG
1 parent f38a249 commit e811172

File tree

3 files changed

+147
-129
lines changed

3 files changed

+147
-129
lines changed

example/src/index.js

Lines changed: 24 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,68 +21,45 @@ class Test extends React.Component {
2121
}
2222

2323
onVcode2Change(v) {
24-
console.log("触发回调onChange", v);
24+
console.log('触发回调onChange', v);
2525
this.setState({
2626
vcode2: v,
2727
});
2828
}
2929

30-
onChangeImg(){
31-
this.setState({
32-
img: this.state.img === 1 ? 2 : 1
33-
})
34-
}
35-
onChangeStr(){
36-
const a = ['a','b','c','d'];
37-
const d = [];
38-
for(let i=0;i<5;i++){
39-
d.push(Math.round(Math.random()*3));
40-
}
41-
this.setState({
42-
code: d.join(""),
43-
})
30+
onChangeImg() {
31+
this.setState({
32+
img: this.state.img === 1 ? 2 : 1,
33+
});
34+
}
35+
onChangeStr() {
36+
const a = ['a', 'b', 'c', 'd'];
37+
const d = [];
38+
for (let i = 0; i < 5; i++) {
39+
d.push(Math.round(Math.random() * 3));
4440
}
41+
this.setState({
42+
code: d.join(''),
43+
});
44+
}
4545

46-
onVcodeClick(){
47-
this.onChangeStr();
48-
}
46+
onVcodeClick() {
47+
this.onChangeStr();
48+
}
4949
render() {
5050
return (
5151
<div>
5252
<div>
53-
<input
54-
type='text'
55-
placeholder="请输入正确的验证码"
56-
value={this.state.input2}
57-
onChange={(e) => this.onInput2Change(e)}
58-
maxLength={20}
59-
/>
60-
<Vcode
61-
onChange={(v) => this.onVcode2Change(v)}
62-
onClick={(v) => this.onVcodeClick(v)}
63-
length={6}
64-
width={200}
65-
height={100}
66-
value={this.state.img === 1 ? ImgTest2 : ImgTest1}
67-
className="classNameTest"
68-
options={{
69-
codes: ['A', 'B', 'C', 'D', 'E'],
70-
lines: 20,
71-
lineWidthMin: 200,
72-
lineWidthMax: 200
73-
}}
74-
/>
53+
<input type="text" placeholder="请输入正确的验证码" value={this.state.input2} onChange={e => this.onInput2Change(e)} maxLength={20} />
54+
<Vcode />
7555
<span>{this.state.input2 === this.state.vcode2 ? '输入正确' : '输入错误'}</span>
7656
</div>
77-
<hr/>
78-
<button onClick={()=>this.onChangeImg()}>更换图片</button>
79-
<button onClick={()=>this.onChangeStr()}>外部生成随机字符串</button>
57+
<hr />
58+
<button onClick={() => this.onChangeImg()}>更换图片</button>
59+
<button onClick={() => this.onChangeStr()}>外部生成随机字符串</button>
8060
</div>
8161
);
8262
}
8363
}
8464

85-
ReactDom.render(
86-
<Test />,
87-
document.getElementById('root')
88-
);
65+
ReactDom.render(<Test />, document.getElementById('root'));

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-vcode",
3-
"version": "1.0.0",
3+
"version": "1.0.1",
44
"description": "a react verification code component",
55
"main": "dist/index.js",
66
"scripts": {
@@ -35,7 +35,8 @@
3535
"webpack-dev-server": "^2.4.5"
3636
},
3737
"dependencies": {
38+
"es6-object-assign": "^1.1.0",
3839
"react": "^16.4.1",
3940
"react-dom": "^16.4.1"
4041
}
41-
}
42+
}

src/index.js

Lines changed: 120 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import React from 'react';
2-
2+
// equire('es6-object-assign').polyfill();
33
class Vcode extends React.Component {
44
constructor(props) {
55
super(props);
66
this.state = {
77
id: this.props.id || `${new Date().getTime()}_${Math.random().toFixed(4)}`, // 需要一个唯一的ID,因为vcode要直接操作dom
8-
width: this.props.width || 150, // vcode宽度
9-
height: this.props.height || 40, // vcode高度
10-
len: this.props.length || 4, // 生成几位code
11-
style: (() => { // vcode容器样式
8+
width: this.props.width || 150, // vcode宽度
9+
height: this.props.height || 40, // vcode高度
10+
len: this.props.length || 4, // 生成几位code
11+
style: (() => {
12+
// vcode容器样式
1213
const a = {
1314
position: 'relative',
1415
backgroundColor: '#fff',
@@ -24,24 +25,75 @@ class Vcode extends React.Component {
2425
}
2526
return a;
2627
})(),
27-
options: (() => { // 初始化参数
28+
options: (() => {
29+
// 初始化参数
2830
const a = {
29-
codes: [ // 所有可能出现的字符
30-
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
31-
'o', 'p', 'q', 'r', 's', 't', 'x', 'u', 'v', 'y', 'z', 'w', 'n',
32-
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
31+
codes: [
32+
// 所有可能出现的字符
33+
'a',
34+
'b',
35+
'c',
36+
'd',
37+
'e',
38+
'f',
39+
'g',
40+
'h',
41+
'i',
42+
'j',
43+
'k',
44+
'l',
45+
'm',
46+
'o',
47+
'p',
48+
'q',
49+
'r',
50+
's',
51+
't',
52+
'x',
53+
'u',
54+
'v',
55+
'y',
56+
'z',
57+
'w',
58+
'n',
59+
'0',
60+
'1',
61+
'2',
62+
'3',
63+
'4',
64+
'5',
65+
'6',
66+
'7',
67+
'8',
68+
'9',
3369
],
34-
fontSizeMin: 22, // 字体尺寸最小值
35-
fontSizeMax: 26, // 字体尺寸最大值
36-
colors: [ // 字可能的颜色
37-
'#117cb3', '#f47b06', '#202890', '#db1821', '#b812c2',
70+
fontSizeMin: 22, // 字体尺寸最小值
71+
fontSizeMax: 26, // 字体尺寸最大值
72+
colors: [
73+
// 字可能的颜色
74+
'#117cb3',
75+
'#f47b06',
76+
'#202890',
77+
'#db1821',
78+
'#b812c2',
3879
],
39-
fonts: [ // 可能的字体
40-
'Times New Roman', 'Georgia', 'Serif', 'sans-serif', 'arial', 'tahoma', 'Hiragino Sans GB',
80+
fonts: [
81+
// 可能的字体
82+
'Times New Roman',
83+
'Georgia',
84+
'Serif',
85+
'sans-serif',
86+
'arial',
87+
'tahoma',
88+
'Hiragino Sans GB',
4189
],
42-
lines: 8, // 生成多少根线
43-
lineColors: [ // 线可能的颜色
44-
'#7999e1', '#383838', '#ec856d', '#008888',
90+
lines: 8, // 生成多少根线
91+
lineColors: [
92+
// 线可能的颜色
93+
'#7999e1',
94+
'#383838',
95+
'#ec856d',
96+
'#008888',
4597
],
4698
lineHeightMin: 1, // 线的粗细最小值
4799
lineHeightMax: 1, // 线的粗细最大值
@@ -63,10 +115,10 @@ class Vcode extends React.Component {
63115

64116
/** 组件参数改变 **/
65117
UNSAFE_componentWillReceiveProps(nextP, nextS) {
66-
if(this.props.value !== nextP.value) {
118+
if (this.props.value !== nextP.value) {
67119
this.onDraw(nextP.value);
68120
}
69-
if(this.props.width !== nextP.width || this.props.height !== nextP.height) {
121+
if (this.props.width !== nextP.width || this.props.height !== nextP.height) {
70122
this.setState({
71123
width: nextP.width,
72124
height: nextP.height,
@@ -78,30 +130,27 @@ class Vcode extends React.Component {
78130
onClick() {
79131
const div = document.getElementById(this.state.id);
80132
// 如果this.props.value有值,表明值是外部受控,这个地方不需要重新渲染
81-
let code = null;
82-
if(!this.props.value){
83-
code = this.onDraw(this.props.value);
84-
}
133+
let code = null;
134+
if (!this.props.value) {
135+
code = this.onDraw(this.props.value);
136+
}
85137
this.props.onClick && this.props.onClick(); // 触发外部的onClick,什么都不返回
86138
}
87139

88140
/** 随机生成一个Code的CSS样式 **/
89-
codeCss(uW,i) {
141+
codeCss(uW, i) {
90142
return [
91-
`font-size:${this.randint(this.state.options.fontSizeMin,
92-
this.state.options.fontSizeMax)}px`,
93-
`color:${this.state.options.colors[this.randint(0,
94-
this.state.options.colors.length - 1)]}`,
143+
`font-size:${this.randint(this.state.options.fontSizeMin, this.state.options.fontSizeMax)}px`,
144+
`color:${this.state.options.colors[this.randint(0, this.state.options.colors.length - 1)]}`,
95145
'position: absolute',
96-
`left:${this.randint(uW * i, ((uW * i) + uW) - (uW / 2))}px`,
146+
`left:${this.randint(uW * i, uW * i + uW - uW / 2)}px`,
97147
'top:50%',
98148
`transform:rotate(${this.randint(-15, 15)}deg) translateY(-50%)`,
99149
`-o-transform:rotate(${this.randint(-15, 15)}deg) translateY(-50%)`,
100150
`-ms-transform:rotate(${this.randint(-15, 15)}deg) translateY(-50%)`,
101151
`-moz-transform:rotate(${this.randint(-15, 15)}deg) translateY(-50%)`,
102152
`-webkit-transform:rotate(${this.randint(-15, 15)}deg) translateY(-50%)`,
103-
`font-family:${this.state.options.fonts[this.randint(0,
104-
this.state.options.fonts.length - 1)]}`,
153+
`font-family:${this.state.options.fonts[this.randint(0, this.state.options.fonts.length - 1)]}`,
105154
'font-weight:bold',
106155
'z-index:2',
107156
].join(';');
@@ -110,53 +159,51 @@ class Vcode extends React.Component {
110159
/** 随机生成一条线的CSS样式 **/
111160
lineCss() {
112161
return [
113-
'position: absolute',
114-
`opacity:${this.randint(3, 8) / 10}`,
115-
`width:${this.randint(this.state.options.lineWidthMin, this.state.options.lineWidthMax)}px`,
116-
`height:${this.randint(this.state.options.lineHeightMin,
117-
this.state.options.lineHeightMax)}px`,
118-
`background:${this.state.options.lineColors[this.randint(0,
119-
this.state.options.lineColors.length - 1)]}`,
120-
`left:${this.randint(-this.state.options.lineWidthMin/2, this.state.width)}px`,
121-
`top:${this.randint(0, this.state.height)}px`,
122-
`transform:rotate(${this.randint(-30, 30)}deg)`,
123-
`-o-transform:rotate(${this.randint(-30, 30)}deg)`,
124-
`-ms-transform:rotate(${this.randint(-30, 30)}deg)`,
125-
`-moz-transform:rotate(${this.randint(-30, 30)}deg)`,
126-
`-webkit-transform:rotate(${this.randint(-30, 30)}deg)`,
127-
`font-family:${this.state.options.fonts[this.randint(0,
128-
this.state.options.fonts.length - 1)]}`,
129-
`font-weight:${this.randint(400, 900)}`,
130-
].join(';');
162+
'position: absolute',
163+
`opacity:${this.randint(3, 8) / 10}`,
164+
`width:${this.randint(this.state.options.lineWidthMin, this.state.options.lineWidthMax)}px`,
165+
`height:${this.randint(this.state.options.lineHeightMin, this.state.options.lineHeightMax)}px`,
166+
`background:${this.state.options.lineColors[this.randint(0, this.state.options.lineColors.length - 1)]}`,
167+
`left:${this.randint(-this.state.options.lineWidthMin / 2, this.state.width)}px`,
168+
`top:${this.randint(0, this.state.height)}px`,
169+
`transform:rotate(${this.randint(-30, 30)}deg)`,
170+
`-o-transform:rotate(${this.randint(-30, 30)}deg)`,
171+
`-ms-transform:rotate(${this.randint(-30, 30)}deg)`,
172+
`-moz-transform:rotate(${this.randint(-30, 30)}deg)`,
173+
`-webkit-transform:rotate(${this.randint(-30, 30)}deg)`,
174+
`font-family:${this.state.options.fonts[this.randint(0, this.state.options.fonts.length - 1)]}`,
175+
`font-weight:${this.randint(400, 900)}`,
176+
].join(';');
131177
}
132178

133179
onDraw(value) {
134-
let c = ''; // 存储生成的code
180+
let c = ''; // 存储生成的code
135181
const div = document.getElementById(this.state.id);
136182
const isImg = /^http[s]*:\/\/|\.jpg$|\.png$|\.jpeg$|\.gif$|\.bmp$|\.webp$|^data:image/.test(value); // 是否是图片
137183
div.innerHTML = '';
138184

139-
if(isImg){ // 用户传递了一张图片
140-
const dom = document.createElement("img");
141-
dom.style.cssText = ["display: block","max-width:100%","max-height:100%"].join(";");
142-
dom.src = value;
143-
div.appendChild(dom);
144-
this.props.onChange && this.props.onChange(null);
145-
return null;
185+
if (isImg) {
186+
// 用户传递了一张图片
187+
const dom = document.createElement('img');
188+
dom.style.cssText = ['display: block', 'max-width:100%', 'max-height:100%'].join(';');
189+
dom.src = value;
190+
div.appendChild(dom);
191+
this.props.onChange && this.props.onChange(null);
192+
return null;
146193
}
147194

148195
// 不是图片而是普通字符串, 如果value存在说明是用户自定义的字符串
149-
let length = value.length || this.state.len; // 字符的长度
196+
let length = value ? value.length : this.state.len; // 字符的长度
150197

151-
const uW = this.state.width / length/1.01; // 每个字符占的宽度
152-
for (let i = 0; i < length; i++) {
153-
const dom = document.createElement('span');
154-
dom.style.cssText = this.codeCss(uW,i);
155-
const temp = value ? value[i] : this.state.options.codes[(Math.round(Math.random() * (this.state.options.codes.length - 1)))];
156-
dom.innerHTML = temp;
157-
c = `${c}${temp}`;
158-
div.appendChild(dom);
159-
}
198+
const uW = this.state.width / length / 1.01; // 每个字符占的宽度
199+
for (let i = 0; i < length; i++) {
200+
const dom = document.createElement('span');
201+
dom.style.cssText = this.codeCss(uW, i);
202+
const temp = value ? value[i] : this.state.options.codes[Math.round(Math.random() * (this.state.options.codes.length - 1))];
203+
dom.innerHTML = temp;
204+
c = `${c}${temp}`;
205+
div.appendChild(dom);
206+
}
160207

161208
// 生成好看的线条
162209
for (let i = 0; i < this.state.options.lines; i++) {
@@ -165,25 +212,18 @@ class Vcode extends React.Component {
165212
div.appendChild(dom);
166213
}
167214
this.props.onChange && this.props.onChange(c); // 触发回调
168-
return c;
215+
return c;
169216
}
170217

171218
/** 生成范围随机数 **/
172219
randint(n, m) {
173-
const c = (m - n) + 1;
174-
const num = (Math.random() * c) + n;
220+
const c = m - n + 1;
221+
const num = Math.random() * c + n;
175222
return Math.floor(num);
176223
}
177224

178225
render() {
179-
return (
180-
<div
181-
id={this.state.id}
182-
style={this.state.style}
183-
className={this.props.className}
184-
onClick={() => this.onClick()}
185-
/>
186-
);
226+
return <div id={this.state.id} style={this.state.style} className={this.props.className} onClick={() => this.onClick()} />;
187227
}
188228
}
189229

0 commit comments

Comments
 (0)