父传子
父组件Login
父组件Login 定义了一个参数叫callBack对应的函数(codeCallBackHanderl)传给子组件,子组件通过props调用,
import RandomImgCode from "@/components/RandomImgCode";
// 子组件传回的方法
codeCallBackHanderl = (value:string) => {
this.setState({
imgCode:value
})
console.log(value,'父组件接受的value')
}
子组件RandomImgCode
import React, { Component } from 'react';
import { RandomImgCodeInterface } from '@/assets/Interface';
class RandomImgCode extends Component{
state = {
code: '',
codeLength: 4,
fontSizeMin: 20,
fontSizeMax: 22,
backgroundColorMin: 240,
backgroundColorMax: 250,
colorMin: 10,
colorMax: 20,
lineColorMin: 40,
lineColorMax: 180,
contentWidth: 120,
contentHeight: 38,
showError: false, // 默认不显示验证码的错误信息
}
canvas:any
componentDidMount() {
this.canvas = React.createRef()
this.randomCode()
}
// 生成随机数
randomNum = (min:any, max:any) => {
return Math.floor(Math.random() * (max - min) + min)
}
// 生成随机颜色
randomColor(min:any, max:any) {
const r = this.randomNum(min, max)
const g = this.randomNum(min, max)
const b = this.randomNum(min, max)
return `rgb(${r}, ${g}, ${b})`
}
drawText(ctx:any, txt:any, i:any) {
ctx.fillStyle = this.randomColor(this.state.colorMin, this.state.colorMax)
const fontSize = this.randomNum(this.state.fontSizeMin, this.state.fontSizeMax)
ctx.font = fontSize + 'px SimHei'
const padding = 10;
const offset = (this.state.contentWidth - 40) / (this.state.code.length - 1)
let x = padding;
if (i > 0) {
x = padding + (i * offset)
}
let y = this.randomNum(this.state.fontSizeMax, this.state.contentHeight - 5)
if (fontSize > 40) {
y = 40
}
const deg = this.randomNum(-10, 10)
// 修改坐标原点和旋转角度
ctx.translate(x, y)
ctx.rotate(deg * Math.PI / 180)
ctx.fillText(txt, 0, 0)
// 恢复坐标原点和旋转角度
ctx.rotate(-deg * Math.PI / 180)
ctx.translate(-x, -y)
}
// 绘制干扰线
drawLine(ctx:any) {
for (let i = 0; i < 1; i++) {
ctx.strokeStyle = this.randomColor(this.state.lineColorMin, this.state.lineColorMax)
ctx.beginPath()
ctx.moveTo(this.randomNum(0, this.state.contentWidth), this.randomNum(0, this.state.contentHeight))
ctx.lineTo(this.randomNum(0, this.state.contentWidth), this.randomNum(0, this.state.contentHeight))
ctx.stroke()
}
}
// 绘制干扰点
drawDot(ctx:any) {
for (let i = 0; i < 100; i++) {
ctx.fillStyle = this.randomColor(0, 255)
ctx.beginPath()
ctx.arc(this.randomNum(0, this.state.contentWidth), this.randomNum(0, this.state.contentHeight), 1, 0, 2 * Math.PI)
ctx.fill()
}
}
// 图片验证码点击事件,重新生成验证码
reloadPic = () => {
this.randomCode()
}
// 随机生成验证码
randomCode() {
let random = ''
// 去掉了I l i o O,可自行添加
const str = 'QWERTYUPLKJHGFDSAZXCVBNMqwertyupkjhgfdsazxcvbnm1234567890'
for (let i = 0; i < this.state.codeLength; i++) {
const index = Math.floor(Math.random() * 57);
random += str[index];
}
this.setState({
code: random
}, () => {
const canvas = this.canvas.current;
const ctx = canvas.getContext('2d')
ctx.textBaseline = 'bottom'
// 绘制背景
ctx.fillStyle = this.randomColor(this.state.backgroundColorMin, this.state.backgroundColorMax)
ctx.fillRect(0, 0, this.state.contentWidth, this.state.contentHeight)
// 绘制文字
for (let i = 0; i < this.state.code.length; i++) {
this.drawText(ctx, this.state.code[i], i)
}
this.drawLine(ctx)
this.drawDot(ctx)
// 绘制后将图片验证码传递回父组件
this.props.callBack(this.state.code)
})
}
render(){
return(
)
}
}
export default RandomImgCode
注意:子组件中一定要定义props类型,不然父组件传值过来会报错
父组件调用子组件的方法:
1.定义一个ref,
2.通过createRef获取ref对象
3.最后父组件点击触发子组件的reloadPic方法