JavaScript初探_5

本文主要参考这里:参考地址,感谢博主。

前言

新增内容包括两部分:

  1. 登陆成功之后进入home页面,home页面有注销按钮可回到第一页;
  2. 登陆页面新增验证码功能

注销按钮

Home.vue

由于要新增加页面,和之前一样,在src/components下新增Home.vue,具体代码如下:

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
<template>
<div>
<el-row type="flex"
justify="center">
<el-col :span="2">
<el-popover placement="top"
width="160"
v-model="visible">
<p>确定注销并退出吗?</p>
<div style="text-align: right; margin: 0">
<el-button size="mini"
type="text"
@click="visible = false">取消</el-button>
<el-button type="primary"
size="mini"
@click="logout">确定</el-button>
</div>
<el-button slot="reference">注销</el-button>
</el-popover>
</el-col>
</el-row>
</div>
</template>

<script>
export default {
methods: {
logout() {
this.$router.replace('/')
},
},
data() {
return {
visible: true
};
}
}
</script>

此页相对简单,只增加了一个注销按钮,并且点击会有Popover弹出框,在element有示例,这里就不具体展开讲了。

具体效果:
注销界面

验证码

验证码这一功能增加过程相对复杂,也比较费时间,最先开始参考了一个最普通的验证码形式,但始终弄不好,后来找到了上述博客,讲解比较详细,经过改动(原博主用到了较为复杂的表单验证,我这里删减了一部分),最后得以实现,首先新建了一个Identify.vue,主要作用是绘制验证码生成图片,具体代码为:

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
146
147
148
149
150
151
152
153
<template>
<div class="s-canvas">
<canvas id="s-canvas"
:width="contentWidth"
:height="contentHeight"></canvas>
</div>
</template>
<script>
export default {
name: 'SIdentify',
props: {
identifyCode: {
type: String,
default: '1234'
},
fontSizeMin: {
type: Number,
default: 16
},
fontSizeMax: {
type: Number,
default: 40
},
backgroundColorMin: {
type: Number,
default: 180
},
backgroundColorMax: {
type: Number,
default: 240
},
colorMin: {
type: Number,
default: 50
},
colorMax: {
type: Number,
default: 160
},
lineColorMin: {
type: Number,
default: 40
},
lineColorMax: {
type: Number,
default: 180
},
dotColorMin: {
type: Number,
default: 0
},
dotColorMax: {
type: Number,
default: 255
},
contentWidth: {
type: Number,
default: 112
},
contentHeight: {
type: Number,
default: 38
}
},
methods: {
// 生成一个随机数
randomNum(min, max) {
return Math.floor(Math.random() * (max - min) + min)
},
// 生成一个随机的颜色
randomColor(min, max) {
var r = this.randomNum(min, max)
var g = this.randomNum(min, max)
var b = this.randomNum(min, max)
return 'rgb(' + r + ',' + g + ',' + b + ')'
},
drawPic() {
var canvas = document.getElementById('s-canvas')
var ctx = canvas.getContext('2d')
ctx.textBaseline = 'bottom'
// 绘制背景
ctx.fillStyle = this.randomColor(
this.backgroundColorMin,
this.backgroundColorMax
)
ctx.fillRect(0, 0, this.contentWidth, this.contentHeight)
// 绘制文字
for (let i = 0; i < this.identifyCode.length; i++) {
this.drawText(ctx, this.identifyCode[i], i)
}
this.drawLine(ctx)
this.drawDot(ctx)
},
drawText(ctx, txt, i) {
ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax)
ctx.font =
this.randomNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei'
var x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1))
var y = this.randomNum(this.fontSizeMax, this.contentHeight - 5)
var deg = this.randomNum(-45, 45)
// 修改坐标原点和旋转角度
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) {
// 绘制干扰线
for (let i = 0; i < 8; i++) {
ctx.strokeStyle = this.randomColor(
this.lineColorMin,
this.lineColorMax
)
ctx.beginPath()
ctx.moveTo(
this.randomNum(0, this.contentWidth),
this.randomNum(0, this.contentHeight)
)
ctx.lineTo(
this.randomNum(0, this.contentWidth),
this.randomNum(0, this.contentHeight)
)
ctx.stroke()
}
},
drawDot(ctx) {
// 绘制干扰点
for (let i = 0; i < 100; i++) {
ctx.fillStyle = this.randomColor(0, 255)
ctx.beginPath()
ctx.arc(
this.randomNum(0, this.contentWidth),
this.randomNum(0, this.contentHeight),
1,
0,
2 * Math.PI
)
ctx.fill()
}
}
},
watch: {
identifyCode() {
this.drawPic()
}
},
mounted() {
this.drawPic()
}
}
</script>

Login.vue同样进行了比较大的修改,最后具体代码为:

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
<template>
<div class="login_content1 ">
<el-row type="flex"
justify="center">
<el-form ref="loginForm"
:model="user"
:rules="loginRules"
status-icon
label-width="80px">
<el-form-item label="用户名"
prop="name">
<el-input v-model="user.name"></el-input>
</el-form-item>
<el-form-item label="密码"
prop="pass">
<el-input v-model="user.pass"
type="password"></el-input>
</el-form-item>
<el-form-item label="验证码"
prop="verifycode">
<!-- 注意:prop与input绑定的值一定要一致,否则验证规则中的value会报undefined,因为value即为绑定的input输入值 -->
<el-input v-model="user.verifycode"
placeholder="请输入验证码"
class="identifyinput"></el-input>
</el-form-item>
<el-form-item>
<div class="identifybox">
<div @click="refreshCode">
<s-identify :identifyCode="identifyCode"></s-identify>
</div>
<el-button @click="refreshCode"
type='text'
class="textbtn">看不清,换一张</el-button>
</div>
</el-form-item>
<el-form-item>
<el-button type="primary"
icon="el-icon-upload"
@click="login">登录</el-button>
</el-form-item>

</el-form>
</el-row>
</div>
</template>

<script>
import SIdentify from '@/components/identify.vue'
export default {

components: {
SIdentify
},
created() {
},
mounted() {
// 验证码初始化
this.identifyCode = ''
this.makeCode(this.identifyCodes, 4)
},
computed: {
},
props: [],
methods: {
login() {
this.$refs.loginForm.validate((valid) => {
if (valid) {
if (this.user.name === 'admin' && this.user.pass === '123') {
this.$notify({
type: 'success',
message: '欢迎你,' + this.user.name + '!',
duration: 3000
})
this.$router.replace('/home')
} else {
this.$message({
type: 'error',
message: '用户名或密码错误',
showClose: true
})
}
}
else {
return false
}
})
},

// 生成随机数
randomNum(min, max) {
return Math.floor(Math.random() * (max - min) + min)
},
// 切换验证码
refreshCode() {
this.identifyCode = ''
this.makeCode(this.identifyCodes, 4)
},
makeCode(o, l) {
for (let i = 0; i < l; i++) {
this.identifyCode += this.identifyCodes[
this.randomNum(0, this.identifyCodes.length)
]
}
console.log(this.identifyCode)
},
},

data() {
// 验证码自定义验证规则
const validateVerifycode = (rule, value, callback) => {
if (value === '') {
callback(new Error('验证码不能为空'))
} else if (value !== this.identifyCode) {
console.log('validateVerifycode:', value)
callback(new Error('验证码不正确!'))
} else {
callback()
console.log('validateVerifycode:', value)
}
}
return {
fontstyle: {},
checked: false,
identifyCodes: '1234567890',
identifyCode: '',
user: {},
loginRules: {
name: [
{ required: true, message: '用户名不能为空', trigger: 'blur' }
],
pass: [
{ required: true, message: '密码不能为空', trigger: 'blur' }
],
verifycode: [
{ required: true, trigger: 'blur', validator: validateVerifycode }
],
}
}
}
}
</script>

具体效果:
验证码登陆

以上。

:转载文章请注明出处,谢谢~