JavaScript笔记-系列
JavaScript基础笔记(1)
JavaScript基础笔记(2)
JavaScript基础笔记(3)
JavaScript笔记DOM操作
JavaScript—DOM案例
QX-AI
GPT-4
QX-AI初始化中...
暂无预设简介,请点击下方生成AI简介按钮。
介绍自己
生成预设简介
推荐相关文章
生成AI简介

搜索框下拉栏

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
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul{
list-style: none;
}
.search-box{
position: relative;
width: 200px;
margin: 20px;
border-radius: 6px;
}
.search-box input{
width: 100%;
height: 40px;
font-size: 16px;
line-height: 100%;
border: 1px solid #65a8e2;
outline: none;
padding: 0 6px;
border-radius: 6px;
transition: all 0.3s;
}
.result-list{
width: 100%;
position: absolute;
top: 40px;
border: 1px solid #65a8e2;
height: auto;
border-top: 0;
background: rgba(200, 236, 243, 0.7);
border-radius: 0 0 6px 6px;
display: none;
}
.result-list li{
height: auto;
}
.result-list a{
transition: all 0.3s;
text-decoration: none;
color: #363636;
padding: 5px 10px;
display: block;
font-size: 14px;
}
.result-list a:hover{
background-color: rgba(210, 210, 210, 0.9);
}
</style>
</head>
<body>
<div class="search-box">
<input type="search" placeholder="输入搜索内容">
<ul class="result-list">
<li><a href="#">搜索词1</a></li>
<li><a href="#">搜索词2</a></li>
<li><a href="#">搜索词3</a></li>
<li><a href="#">搜索词4</a></li>
<li><a href="#">搜索词5</a></li>
<li><a href="#">搜索词6</a></li>
</ul>
</div>
<script>
const input = document.querySelector('input');
const list = document.querySelector('.result-list');
input.addEventListener('focus',()=>{
list.style.display = "block";
input.style.borderRadius = '6px 6px 0 0'
});
input.addEventListener('blur',()=>{
list.style.display = "none";
input.style.borderRadius = '6px'
});
</script>
</body>
</html>

评论发布、字数统计

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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
box-sizing: border-box;
}

.comment-box {
display: flex;
width: 500px;
position: relative;
transition: all 0.3s;
}

.comment-avatar {
border-radius: 50%;
width: 50px;
height: 50px;
background: url('https://cdn.qcqx.cn/img/head.webp') no-repeat center / cover;
margin-right: 15px;
}

#comment-tx {
outline: none;
border-color: transparent;
resize: none;
background: #f5f5f5;
border-radius: 4px;
flex: 1;
padding: 10px;
transition: all 0.3s;
font-size: 12px;
height: 60px;
}

#comment-tx:focus {
border-color: #e4e4e4;
background: #fff;
height: 85px;
}

.comment-box button {
background: #00aeec;
color: #fff;
border: none;
border-radius: 4px;
margin-left: 10px;
width: 70px;
cursor: pointer;
transition: all 0.3s;
}

.comment-count {
width: 500px;
height: auto;
display: flex;
justify-content: flex-end;
}

.comment-count span {
margin-right: 80px;
color: #999;
margin-top: 5px;
transition: all 0.3s;
opacity: 0;
}

.content-list {
display: flex;
width: 500px;
position: relative;
transition: all 0.3s;
flex-direction: column;
flex-wrap: nowrap;
}

.content-item {
display: flex;
border-bottom: 1px solid #e4e4e4;
padding-bottom: 10px;
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;
margin-bottom: 15px;
}

.content-avatar {
border-radius: 50%;
width: 50px;
height: 50px;
background: url('https://cdn.qcqx.cn/img/head.webp') no-repeat center / cover;
margin-right: 15px;
}

.content-warp {
width: calc(100% - 65px);
padding-right: 8px;
}

.content-name {
font-size: 16px;
margin-bottom: 6px;
}

.content-comment {
font-size: 18px;
white-space: normal;
word-break: break-all;
word-wrap: break-word;
text-overflow: ellipsis;
}
</style>
</head>

<body>
<div class="comment-box">
<div class="comment-avatar"></div>
<textarea id="comment-tx" placeholder="发一条友善的评论,回车发布评论" maxlength="200"></textarea>
<button>发布</button>
</div>
<div class="comment-count">
<span>0/200字</span>
</div>
<div class="content-list">
<div class="content-item">
<div class="content-avatar"></div>
<div class="content-warp">
<div class="content-name">chuckle</div>
<div class="content-comment">评论一</div>
</div>
</div>
<div class="content-item">
<div class="content-avatar"></div>
<div class="content-warp">
<div class="content-name">chuckle</div>
<div class="content-comment">22222222222222222222222222222222222222222222222222222222222222222222222222
</div>
</div>
</div>
</div>
<script>
// 评论输入框
const count = document.querySelector('.comment-count span');
const tx = document.querySelector('#comment-tx');
tx.addEventListener('focus', () => {
count.style.opacity = 1;
});
tx.addEventListener('blur', () => {
count.style.opacity = 0;
});
tx.addEventListener('input', () => {
count.innerHTML = `${tx.value.length}/200字`
});
// 评论展示
const contentList = document.querySelector('.content-list');
function applyComment() {
let comment = tx.value;
let html = `<div class="content-item">
<div class="content-avatar"></div>
<div class="content-warp">
<div class="content-name">chuckle</div>
<div class="content-comment">${comment}</div>
</div>
</div>`;
contentList.insertAdjacentHTML('afterbegin', html);
}
tx.addEventListener('keyup', (e) => {
if (e.key == 'Enter') {
if (tx.value.trim()) {
applyComment();
}
tx.value = '';
count.innerHTML = `${tx.value.length}/200字`
}
})
const button = document.querySelector('.comment-box button');
button.addEventListener('click', () => {
if (tx.value.trim()) {
applyComment();
}
tx.value = '';
count.innerHTML = `${tx.value.length}/200字`
})
</script>
</body>
</html>

轮播图

当然还是直接用插件方便swiper

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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.rot-box {
max-width: 560px;
height: 400px;
overflow: hidden;
border-radius: 12px;
box-shadow: 0 3px 8px 6px rgba(7, 17, 27, 0.05);
margin: 10px;
}

.rot-img {
width: 100%;
height: 80%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
position: relative;
}

.rot-img img {
width: 100%;
height: 100%;
object-fit: cover;
}

.rot-footer {
height: 20%;
background-color: rgb(100, 67, 68);
padding: 12px 12px 0 12px;
position: relative;
}

.rot-toggle {
position: absolute;
right: 10px;
top: 15px;
display: flex;
}

.rot-toggle button {
margin-right: 12px;
width: 28px;
height: 28px;
appearance: none;
border: none;
background: rgba(255, 255, 255, 0.1);
color: #fff;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
}

.rot-toggle button:hover {
background: rgba(255, 255, 255, 0.2);
}

.rot-title {
margin: 0;
color: #fff;
font-size: 18px;
margin-bottom: 10px;
margin-left: 10px;
}

ul.rot-select {
margin: 0;
padding: 0;
list-style: none;
display: flex;
align-items: center;
margin-left: 10px;
height: 12px;
}

ul.rot-select li {
width: 8px;
height: 8px;
margin: 4px;
border-radius: 50%;
background: #fff;
opacity: 0.4;
cursor: pointer;
transition: all 0.3s;
}

ul.rot-select li.active {
width: 12px;
height: 12px;
opacity: 1;
}
@media screen and (max-width:500px) {
.rot-box {
height: 320px;
}
}
</style>
</head>

<body>
<div class="rot-box">
<div class="rot-img">
<img src="https://cdn.qcqx.cn/images/41-1.webp">
</div>
<div class="rot-footer">
<div class="rot-title">标题零</div>
<ul class="rot-select">
<li class="active"></li>
</ul>
<div class="rot-toggle">
<button class="rot-prev">&lt;</button>
<button class="rot-next">&gt;</button>
</div>
</div>
</div>
<script>
const rotDate = [
{
url: 'https://cdn.qcqx.cn/images/43-1.webp',
title: '标题一'
},
{
url: 'https://cdn.qcqx.cn/images/42-1.webp',
title: '标题二'
},
{
url: 'https://cdn.qcqx.cn/images/41-1.webp',
title: '标题三'
},
{
url: 'https://cdn.qcqx.cn/images/38-1.webp',
title: '标题四'
},
{
url: 'https://cdn.qcqx.cn/images/39-1.webp',
title: '标题五'
},
];
//生成[0,arr长度)的随机整数
function getRandom(arr) {
return parseInt(Math.random() * arr.length);
}
const rotSelect = document.querySelector('.rot-select');
// 数组中有多少对象加几个li
rotSelect.innerHTML = '';// 先清空ul的内容
for (let i = 0; i < rotDate.length; i++) {
rotSelect.innerHTML += '<li></li>';
}
//让第一个li变成小白点
document.querySelector('.rot-select li:first-child').classList.toggle('active');
// 一开始随机选一张
// 获取要操作的元素
const img = document.querySelector('.rot-img img');
const title = document.querySelector('.rot-title');
const rot_li = document.querySelectorAll('.rot-select li');
// 数据数组长度
const dateLength = rotDate.length;
// 轮播展示序号,默认第一个
var num = 0;
// 轮播的对象,默认第一个
var rot = rotDate[num];
// 修改轮播容器的内容
function applyDate() {
//换标题和图片
rot = rotDate[num];
img.src = rot.url;
title.innerHTML = rot.title;
//移除之前的小白点,给当前li添加小白点
if (document.querySelector('.rot-select .active')) {
document.querySelector('.rot-select .active').classList.remove('active');
}
rot_li[num].classList.toggle('active');
}
// 随机展示一个
function ranDate(){
var random = getRandom(rotDate);
rot = rotDate[random];
num = random;
applyDate();
}
// 上一张
function prevDate() {
num > 0 ? --num : num = dateLength - 1;
applyDate();
}
// 下一张
function nextDate() {
//控制下一张是哪个
num = ++num % dateLength;
applyDate();
}
//获取两个按钮
const rotPrev = document.querySelector('.rot-prev');
const rotNext = document.querySelector('.rot-next');
//注册事件
rotPrev.addEventListener('click', () => {
prevDate();
})
rotNext.addEventListener('click', () => {
nextDate();
})
// 点击小圆点切换展示
rot_li.forEach((item, index, arr) => {
item.addEventListener('click', () => {
//让轮播展示序号变为当前点击的li的序号
num = index;
applyDate();
});
});
// 鼠标悬停停止轮播
const rotBox = document.querySelector('.rot-box');
rotBox.addEventListener('mouseenter',()=>{
clearInterval(itv);
console.log('暂停轮播');
});
// 鼠标移出恢复轮播
rotBox.addEventListener('mouseleave',()=>{
//未确保不重复定时,先清除一次
clearInterval(itv);
itv = setInterval(nextDate, 1000);
console.log('恢复轮播');
});
// 一开始随机展示一个,注释掉则默认展示第一个
//ranDate();
// 定时器轮播
var itv = setInterval(nextDate, 1000);

</script>
</body>
</html>

tab切换

1、for循环注册鼠标悬停版:

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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

.tab-box {
width: 500px;
border-radius: 6px;
overflow: hidden;
}

.tab-nav {
width: 100%;
height: 40px;
display: flex;
background: rgb(233, 233, 233);
justify-content: center;
border-bottom: 1px solid #333;
}

.tab-nav ul {
list-style: none;
display: flex;
align-items: flex-end;
}

.tab-nav ul li {
margin: 0 5px;
padding: 2px 15px 0;
font-size: 18px;
border-radius: 6px 6px 0 0;
transition: all 0.3s;
border-bottom: 1px solid #333;
margin-bottom: -1px;
}
.tab-nav ul li.active {
background: rgb(220, 220, 220);
border-bottom: 1px solid rgb(220, 220, 220);
}
.tab-nav ul li a {
text-decoration: none;
color: #333;
height: 30px;
display: block;
}

.tab-content {
width: 100%;
height: 100px;
background: rgb(220, 220, 220);
}
.tab-item{
display: none;
}
.tab-item.active{
display: block;
text-align: center;
padding: 10px;
font-size: 20px;
}
</style>
</head>

<body>
<div class="tab-box">
<div class="tab-nav">
<ul>
<li class="active"><a href="javascript:;">栏1</a></li>
<li><a href="javascript:;">栏2</a></li>
<li><a href="javascript:;">栏3</a></li>
<li><a href="javascript:;">栏4</a></li>
<li><a href="javascript:;">栏5</a></li>
</ul>
</div>
<div class="tab-content">
<div class="tab-item active">项目一</div>
<div class="tab-item">项目二</div>
<div class="tab-item">项目三</div>
<div class="tab-item">项目四</div>
<div class="tab-item">项目五</div>
</div>
</div>
<script>
const tabNav = document.querySelectorAll('.tab-nav ul li');
const tabItem = document.querySelectorAll('.tab-item');
tabNav.forEach((item,index)=>{
item.addEventListener('mouseenter',()=>{
document.querySelector('.tab-nav .active').classList.remove('active');
document.querySelector('.tab-content .active').classList.remove('active');
item.classList.add('active');
tabItem[index].classList.add('active');
});
});
</script>
</body>
<div id="tab-sandbox"></div>
</html>

2、事件委托鼠标点击版:

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

.tab-box {
width: 500px;
border-radius: 6px;
overflow: hidden;
margin: 10px;
}

.tab-nav {
width: 100%;
height: 40px;
display: flex;
background: rgb(233, 233, 233);
justify-content: center;
border-bottom: 1px solid #333;
}

.tab-nav ul {
list-style: none;
display: flex;
align-items: flex-end;
}

.tab-nav ul li {
margin: 0 5px;
font-size: 18px;
border-bottom: 1px solid transparent;
margin-bottom: -1px;
}

.tab-nav ul li a.active {
background: rgb(220, 220, 220);
border-bottom: 1px solid rgb(220, 220, 220);
}

.tab-nav ul li a {
text-decoration: none;
color: #333;
height: 33px;
display: block;
padding: 2px 15px;
border-radius: 6px 6px 0 0;
transition: all 0.3s;
}

.tab-content {
width: 100%;
height: 100px;
background: rgb(220, 220, 220);
}

.tab-item {
display: none;
}

.tab-item.active {
display: block;
text-align: center;
padding: 10px;
font-size: 20px;
}
</style>
</head>

<body>
<div class="tab-box">
<div class="tab-nav">
<ul>
<li><a href="javascript:;" data-id="0" class="active">栏1</a></li>
<li><a href="javascript:;" data-id="1">栏2</a></li>
<li><a href="javascript:;" data-id="2">栏3</a></li>
<li><a href="javascript:;" data-id="3">栏4</a></li>
<li><a href="javascript:;" data-id="4">栏5</a></li>
</ul>
</div>
<div class="tab-content">
<div class="tab-item active">项目一</div>
<div class="tab-item">项目二</div>
<div class="tab-item">项目三</div>
<div class="tab-item">项目四</div>
<div class="tab-item">项目五</div>
</div>
</div>
<script>
const tabNav = document.querySelector('.tab-nav ul');
const tabItem = document.querySelectorAll('.tab-item');
//利用事件委托减少注册
tabNav.addEventListener('click', (e) => {
let tag = e.target.tagName;
if (tag === 'A') {
document.querySelector('.tab-nav .active').classList.remove('active');
document.querySelector('.tab-content .active').classList.remove('active');
e.target.classList.add('active');
tabItem[e.target.dataset.id].classList.add('active')
}
});
</script>
</body>

</html>

表单全选反选

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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #c0c0c0;
width: 500px;
text-align: center;
}

th {
background-color: rgb(40, 170, 220);
font: bold 16px;
color: #fff;
height: 22px;
}
td {
border: 1px solid #d0d0d0;
color: #363636;
padding: 6px 10px;
background: #f9f9f9;
}
tr td:not(:first-child){
min-width: 50px;
}
tr th:first-child{
width: 70px;
}
</style>
</head>

<body>
<table>
<tr>
<th>
<input type="checkbox" id="check-all">
<span>全选</span>
</th>
<th>书名</th>
<th>作者</th>
<th>价格</th>
</tr>
<tr>
<td>
<input type="checkbox" class="check-one">
</td>
<td>毛泽东选集</td>
<td>毛泽东</td>
<td>56</td>
</tr>
<tr>
<td>
<input type="checkbox" class="check-one">
</td>
<td>资本论</td>
<td>马克思</td>
<td>129</td>
</tr>
<tr>
<td>
<input type="checkbox" class="check-one">
</td>
<td>三体</td>
<td>刘慈欣</td>
<td>46</td>
</tr>
</table>
<script>
const checkAll = document.querySelector('#check-all');
const checks = document.querySelectorAll('.check-one');
checkAll.addEventListener('click',()=>{
checks.forEach((item)=>{
item.checked = checkAll.checked;
});
});
checks.forEach((item)=>{
item.addEventListener('click',()=>{
checkAll.checked = document.querySelectorAll('.check-one:checked').length === checks.length;
})
})
</script>
</body>

</html>

导航栏、电梯导航、哔哩tab

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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
padding-bottom: 500px;
}

.tab-box {
width: 500px;
height: auto;
border-radius: 6px;
overflow: hidden;
margin: 10px;
}

.tab-nav {
display: flex;
list-style: none;
border-bottom: 1px solid #333;
background: rgb(233, 233, 233);
height: 40px;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
align-items: center;
position: relative;
}

.tab-nav a {
margin: 5px;
padding: 0 10px;
text-decoration: none;
color: #000;
height: 40px;
line-height: 40px;
}

.tab-nav a.active {
color: rgb(23, 180, 215);
}

.tab-bar {
position: absolute;
width: 40px;
height: 3px;
background: rgb(23, 180, 215);
bottom: -1px;
transition: all 0.3s;
}

.item-box {
background: rgb(220, 220, 220);
}

.item {
text-align: center;
padding: 10px;
display: none;
}

.item.active {
display: block;
height: 100px;
}

/* 导航栏 */
#nav {
width: 100%;
height: 50px;
text-align: center;
line-height: 50px;
background: rgba(120, 182, 191, 0.5);
font-size: 20px;
position: fixed;
top: -50px;
transition: all 0.3s;
z-index: 9999;
}

.box {
margin-top: 10px;
width: 200px;
height: 200px;
background: rgb(144, 193, 230);
margin-bottom: 200px;
border-radius: 6px;
}

/* 电梯导航 */
.ele-nav {
position: fixed;
bottom: 20%;
background: rgb(233, 233, 233);
right: 10%;
border: 1px solid #333;
border-bottom: 0;
border-radius: 6px;
overflow: hidden;
transition: all 0.3s;
opacity: 0;
z-index: -99;
}
.ele-item.active{
color: rgb(23, 180, 215);
background: rgb(252, 200, 200);
}
.ele-item,
.back-top {
padding: 10px;
border-bottom: 1px solid #333;
user-select: none;
transition: all 0.3s;
}
.ele-item:hover,
.back-top:hover{
color: rgb(23, 180, 215);
}
</style>
</head>

<body>
<div id="nav">导航栏</div>
<div class="tab-box">
<div class="tab-nav">
<a href="javascript:;" class="active">栏1</a>
<a href="javascript:;">栏2</a>
<a href="javascript:;">栏3</a>
<a href="javascript:;">栏4</a>
<a href="javascript:;">栏114514</a>
<div class="tab-bar"></div>
</div>

<div class="item-box">
<div class="item active">项目一</div>
<div class="item">项目二</div>
<div class="item">项目三</div>
<div class="item">项目四</div>
<div class="item">项目114514</div>
</div>
</div>
<div class="ele-nav">
<div class="ele-item">去第一个</div>
<div class="ele-item">去第二个</div>
<div class="ele-item">去第三个</div>
<div class="ele-item">去第四个</div>
<div class="back-top">回到顶部</div>
</div>
<div class="box">第一个盒子,滚动到此(往上55像素)显示导航栏和电梯导航</div>
<div class="box">第二个盒子</div>
<div class="box">第三个盒子</div>
<div class="box">第四个盒子</div>
<script>
//网页导航栏,还有电梯导航的显示和隐藏
const nav = document.querySelector('#nav');
const box = document.querySelectorAll('.box');
const ele_nav = document.querySelector('.ele-nav');
window.addEventListener('scroll', () => {
let n = window.scrollY;
let m = box[0].offsetTop;
let tf = n >= m-55;//减去55像素,不让电梯导航点击去第一个后消失
nav.style.top = tf ? '0px' : '-50px';
ele_nav.style.opacity = tf ? '1' : '0';
ele_nav.style.zIndex = tf ? '99' : '-99';
});
//bilibili导航
const bar = document.querySelector('.tab-bar');
const tabNav = document.querySelector('.tab-nav');
const tab_a = document.querySelectorAll('.tab-nav a');
const item = document.querySelectorAll('.item-box .item');
//给每个a依次添加data-id
tab_a.forEach((item, index) => {
item.dataset.id = index;
});
//将a的点击事件委托给tab-nav
tabNav.addEventListener('click', (e) => {
let tag = e.target.tagName;
if (tag === 'A') {
//tab导航切换
document.querySelector('.tab-nav a.active').classList.remove('active');
document.querySelector('.item.active').classList.remove('active');
e.target.classList.add('active');
item[e.target.dataset.id].classList.add('active');
//bar移动和动态改变宽度
bar.style.width = `${e.target.offsetWidth}px`;
bar.style.left = `${e.target.offsetLeft}px`;
}
});
tab_a[0].click();//先初始化一次bar的位置
//电梯导航
//给每个电梯导航依次添加data-name
document.querySelectorAll('.ele-item').forEach((item, index) => {
item.dataset.name = `b${index+1}`;
});
//给每个box依次添加电梯导航对应的自定义属性的class
box.forEach((item, index) => {
item.classList.add(`b${index+1}`);
});
//移除ele的active
function reactive(){
let ele_active = document.querySelector('.ele-item.active');
if(ele_active){
//如果有,先清除
ele_active.classList.remove('active');
}
}
//去指定盒子,事件委托
ele_nav.addEventListener('click', (e) => {
let cname = e.target.className;
if (cname === 'ele-item'||cname === 'ele-item active') {
reactive();
//给点击的item添加active
e.target.classList.add('active');
//去对应的盒子
//通过自定义属性获取对应的盒子class名
let box = document.querySelector(`.${e.target.dataset.name}`);
// 其实监听滚动后,没必要再手动去给active,但想点击后导航立刻变色的话,可以取消下面的注释
// //先立刻移除页面滚动监听
// window.removeEventListener('scroll', scroll_light_ele);
// //一秒后重新监听
// setTimeout(() => {
// //防止重复注册,先移除页面滚动监听
// window.removeEventListener('scroll', scroll_light_ele);
// window.addEventListener('scroll', scroll_light_ele);
// }, 800);
//更新当前页面在哪个盒子的范围位置
box_num = e.target.dataset.name.replace(/[^\d]/g, " ");
//滚动到指定位置
window.scrollTo({
top: box.offsetTop - 50,
left: 0,
behavior: 'smooth'
});
}
//点击返回顶部
if (cname === 'back-top') {
reactive();
window.scrollTo({
top: 0,
left: 0,
behavior: 'smooth'
});
box_num = -1;
}
});
//获取盒子的高度数组减去55px
const box_top_arr = Array.from(box).map((item)=>{
return item.offsetTop-55;
})
var box_num = -1;//记录当前在哪个盒子范围内
//页面滚动到对应box让电梯导航对应导航高亮
function scroll_light_ele(){
let n = window.scrollY;
let num = box_top_arr.reduce((prev, item, index)=>{
return n >= item ? index : prev;
},-1);
if(num === box_num){
//说明还在这个盒子范围内,直接返回
return;
}else{
//更新位置
box_num = num;
}
if(num > -1){
reactive();
document.querySelector(`[data-name="b${num+1}"]`).classList.add('active');
}else{
box_num = -1;
}
}
window.addEventListener('scroll', scroll_light_ele);
</script>
</body>

</html>

倒计时

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}

.time-box {
padding: 20px 15px;
background: rgb(30, 171, 210);
width: fit-content;
border-radius: 6px;
overflow: hidden;
margin: 10px;
font-size: 18px;
}

.time-now {
width: 100%;
text-align: center;
}

.time-title {
font-size: 26px;
text-align: center;
width: 100%;
margin: 6px 0;
}

.clock {
display: flex;
width: 100%;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
align-content: center;
margin: 10px 0;
}
.hour,.minutes,.second{
font-size: 20px;
margin: 2px;
padding: 2px 3px;
border-radius: 4px;
background: rgba(36, 36, 36, 0.65);
color: #fff;
}
.colon{
font-size: 20px;
font-weight: bolder;
padding: 2px;
}
.target{
width: 100%;
text-align: center;
margin: 6px 0 0;
}
</style>
</head>

<body>
<div class="time-box">
<div class="time-now">今天是1970年1月1日</div>
<div class="time-title">倒计时</div>
<div class="clock">
<div class="hour">00</div>
<div class="colon">:</div>
<div class="minutes">00</div>
<div class="colon">:</div>
<div class="second">00</div>
</div>
<div class="target">目标时间00:00:00</div>
</div>

<script>
const hour = document.querySelector('.hour');
const minutes = document.querySelector('.minutes');
const second = document.querySelector('.second');
const time_now = document.querySelector('.time-now');
const target = document.querySelector('.target');
const now = new Date();
const time = '18:00:00';
const targetTime = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()} 18:00:00`;
const last = new Date(targetTime);
let count = (last.getTime() - now.getTime()) / 1000;
function countDown() {
let h = parseInt(count / 60 / 60 % 24);
h = h < 10 ? '0' + h : h;
let m = parseInt(count / 60 % 60);
m = m < 10 ? '0' + m : m;
let s = parseInt(count % 60);
s = s < 10 ? '0' + s : s;
hour.innerHTML = h;
minutes.innerHTML = m;
second.innerHTML = s;
count--;
if (count == 0) {
count = 0;
}
}
time_now.innerHTML = `今天是${now.getFullYear()}${now.getMonth() + 1}${now.getDate()}日`;
target.innerHTML = `目标时间${time}`
countDown();
setInterval(countDown, 1000);
</script>
</body>

</html>

学生信息表

学生信息表

本地存储,数据驱动,刷新不丢失

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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

a {
text-decoration: none;
color: rgb(226, 14, 14);
}

.info-box {
width: 800px;
margin: 0 auto;
position: relative;
}

h1 {
text-align: center;
margin: 20px;
user-select: none;
}

.info {
width: 100%;
text-align: center;
margin: 40px 0;
}

.ipt-name {
width: fit-content;
display: inline-block;
line-height: 25px;
font-size: 16px;
}

.info input,
.info select {
width: 70px;
outline: none;
border-radius: 5px;
border: 1px solid #b8daff;
height: 25px;
padding: 0 5px;
margin: 0 15px 0 2px;
}

input.sname {
width: 80px;
}

input.age {
width: 40px;
}

.info button {
width: 60px;
height: 25px;
border-radius: 5px;
cursor: pointer;
background: rgb(82, 191, 231);
outline: none;
border: 1px solid rgb(98, 98, 98);
color: #fff;
font-size: 15px;
}

table {
margin: 0 auto;
width: 100%;
padding: 0 20px;
color: #363636;
border-collapse: collapse;
border-spacing: 0;
}

th {
padding: 5px 10px;
background: #cfe5ff;
font-size: 20px;
font-weight: 400;
}

td,
th {
border: 1px solid #b8daff;
}

td {
padding: 5px 10px;
text-align: center;
font-size: 16px;
}

tbody tr {
background: #fff;
}

tbody tr:hover {
background: #e1ecf8;
}
.info-num{
right: 10px;
width: fit-content;
position: absolute;
margin-top: -20px;
}
</style>
</head>

<body>
<div class="info-box">
<h1>新增学生信息</h1>
<form class="info" autocomplete="off">
<div class="ipt-name">姓名</div>
<input type="text" class="sname" name="sname">
<div class="ipt-name">年龄</div>
<input type="text" class="age" name="age">
<div class="ipt-name">性别</div>
<select class="gender" name="gender">
<option value="男"></option>
<option value="女"></option>
</select>
<div class="ipt-name">年级</div>
<select class="grade" name="grade">
<option value="大一">大一</option>
<option value="大二">大二</option>
<option value="大三">大三</option>
<option value="大四">大四</option>
</select>
<div class="ipt-name">专业</div>
<select class="major" name="major">
<option value="计科">计科</option>
<option value="机械">机械</option>
<option value="会计">会计</option>
</select>
<button class="add-info">录入</button>
</form>
<h1>学生信息</h1>
<div class="info-num">共有0条数据</div>
<table>
<thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>年级</th>
<th>专业</th>
<th>操作</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<script>
var arr = [
{
name: '张三',
age: 19,
gender: '男',
grade: '大一',
major: '计科'
},
{
name: '李四',
age: 18,
gender: '男',
grade: '大二',
major: '机械'
},
{
name: '李丽',
age: 18,
gender: '女',
grade: '大三',
major: '会计'
}
];
const info = document.querySelector('.info');
const items = document.querySelectorAll('.info [name]');
const tbody = document.querySelector('tbody');
const infoNum = document.querySelector('.info-num');
info.addEventListener('submit', (e) => {
e.preventDefault();
let i = Array.from(items).reduce((prev, item) => {
return item.value === '' ? prev : prev += 1;
}, 0);
console.log(i);
if (i != items.length) {
return alert('输入内容不能为空');
}
let obj = {
name: info.children[1].value,
age: info.children[3].value,
gender: info.children[5].value,
grade: info.children[7].value,
major: info.children[9].value
}
console.log(obj);
//更新数据
arr.push(obj);
//重置表单
info.reset();
//信息本地存储
localStorage.setItem('info', JSON.stringify(arr));
//调用渲染函数
render();
});
function render() {
tbody.innerHTML = '';
let trArr = arr.map((item, index) => {
return `<tr>
<td>${index + 1}</td>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.gender}</td>
<td>${item.grade}</td>
<td>${item.major}</td>
<td><a href="javascript:">删除</a></td>
</tr>`
});
tbody.innerHTML = trArr.join('');
infoNum.innerHTML = `共有${arr.length}条数据`;
}
//删除,事件委托
tbody.addEventListener('click', (e) => {
let target = e.target;
if (target.tagName === 'A') {
let num = e.target.parentNode.parentNode.firstElementChild.innerHTML
//拿到序号,删除一个
let tf = confirm(`确认删除第 ${num} 个学生信息吗?`);
if (tf) {
arr.splice(num - 1, 1);
localStorage.setItem('info', JSON.stringify(arr));
render();
}
}
});
function infoInit() {
//先获取本地数据
let info = JSON.parse(localStorage.getItem('info'));
if (info) {
arr = info;
}
render();
}
//初始化
infoInit();
</script>
</body>

</html>

注册界面

注册界面

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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

input {
outline: none;
}

a {
text-decoration: none;
}

.reg-box {
margin: 0 auto;
width: auto;
height: auto;
background: rgb(244, 242, 242);
position: absolute;
top: 50%;
left: 50%;
border-radius: 6px;
transform: translate(-50%, -50%);
border: 1px solid #e4e4e4;
}

.reg-box .reg-title {
width: 100%;
text-align: center;
margin: 15px 0;
font-size: 22px;
font-weight: bolder;
color: #363636;
}

.reg-form {
margin: 10px;
}

.form-item {
display: flex;
position: relative;
width: 300px;
flex-direction: row;
flex-wrap: wrap;
padding-bottom: 25px;
justify-content: space-between;
letter-spacing: 0.6px;
}

.form-item input {
width: 100%;
border: 1px solid #e4e4e4;
height: 40px;
font-size: 16px;
padding: 10px 16px;
border-radius: 6px;
}

.form-item .msg {
position: absolute;
line-height: 1;
width: 100%;
font-size: 12px;
color: rgb(255, 79, 126);
bottom: 9px;
padding-left: 5px;
}

.code-box {
display: flex;
}

.form-item [name="code"] {
flex-shrink: 1;
}

.form-item a.code {
width: fit-content;
height: 40px;
line-height: 40px;
background: rgb(120, 187, 233);
text-align: center;
border-radius: 6px;
color: #fff;
margin-left: 10px;
padding: 0 10px;
flex-shrink: 0;
display: block;
transition: all 0.3s;
user-select: none;
}

.agree-check {
margin: 0 auto;
width: fit-content;
}

.form-item .agree {
width: 20px;
height: 20px;
cursor: pointer;
}

.form-item .agree:checked {
background: #9decbe;
}

.agreement {
width: calc(100% - 20px);
padding-left: 10px;
color: #363636;
line-height: 20px;
height: 20px;
}

.agreement a {
color: #6a9adf;
}

.reg-submit {
margin: 0 auto;
display: block;
width: calc(100% - 40px);
height: 40px;
border-radius: 8px;
outline: none;
border: none;
background: #9decbe;
font-size: 18px;
color: #363636;
margin-bottom: 15px;
transition: all 0.3s;
cursor: pointer;
user-select: none;
}

.reg-submit:hover {
background: #86ebb0;
}

.form-item .see {
position: absolute;
width: fit-content;
height: auto;
right: 10px;
line-height: 1;
cursor: pointer;
font-size: 14px;
top: 12px;
color: #ababab;
transition: all 0.3s;
user-select: none;
}

.form-item .see:hover {
color: #6a9adf;
}
</style>
</head>

<body>
<div class="reg-box">
<div class="reg-title">新用户注册</div>
<form class="reg-form">
<div class="form-item">
<input name="uname" type="text" placeholder="设置用户名" maxlength="12" autocomplete="off">
<div class="msg"></div>
</div>
<div class="form-item">
<input name="phone" type="text" placeholder="输入手机号" maxlength="11" autocomplete="off">
<div class="msg"></div>
</div>
<div class="form-item">
<div class="code-box">
<input name="code" type="text" placeholder="输入验证码" maxlength="6" autocomplete="off">
<div class="msg"></div>
<a href="javascript:;" class="code">发送验证码</a>
</div>
</div>
<div class="form-item">
<input name="password" type="password" placeholder="输入密码" maxlength="20" autocomplete="off">
<div class="msg"></div>
<div class="see">显示</div>
</div>
<div class="form-item">
<input class="password-again" type="password" placeholder="再次输入密码" maxlength="20" autocomplete="off">
<div class="msg"></div>
<div class="see">显示</div>
</div>
<div class="form-item agree-check">
<input type="checkbox" class="agree" autocomplete="off">
<div class="msg"></div>
<div class="agreement">已阅读并同意<a href="#">《用户协议》</a></div>
</div>
<button class="reg-submit">提交</button>
</form>
</div>

<script>
const code = document.querySelector('.code-box .code');
var code_flag = true;//控制点击有没有效果
const codeTime = 30;//验证码发送间隔时间,默认30秒
//验证码间隔验证的初始化
function codeInit() {
//如果验证码间隔倒计时还没30秒,就继续倒计时
let code_time = localStorage.getItem('code_time');
if (code_time) {
let time = codeTime - parseInt((new Date().getTime() - code_time) / 1000);
//小于0说明间隔已经满足
if (time > 0) {
//执行控制验证码间隔函数
code_limit_time(time);
}
}
// 发送短信验证码
code.addEventListener('click', () => {
if (code_flag) {
//存入点击发送验证码时的时间戳
localStorage.setItem('code_time', new Date().getTime());
code_flag = false;//可以点击
code_limit_time();
//这里就可以去做请求短信接口
}
});
}
// 控制验证码发送间隔函数
function code_limit_time(i = codeTime) {
code.innerHTML = `${i}秒后重新获取`;
code.style.pointerEvents = 'none';
code.style.background = '#c6c6c6';
var stv = setInterval(() => {
i--;
code.innerHTML = `${i}秒后重新获取`;
if (i === 0) {
code_flag = true;
code.innerHTML = `重新获取`;
code.style.pointerEvents = 'auto';
code.style.background = 'rgb(120, 187, 233)';
clearInterval(stv);
//倒计时完成移除时间戳
localStorage.removeItem('code_time');
}
}, 1000)
}
//输入框验证函数
function input_verification(input, rex, msg) {
let div = input.nextElementSibling;
if (rex.test(input.value)) {
div.innerHTML = "";
return true;
} else {
div.innerHTML = msg;
return false;
}
}

// 输入框内容检查
const uname = document.querySelector('.form-item input[name="uname"]');
const phone = document.querySelector('.form-item input[name="phone"]');
const code_input = document.querySelector('.form-item input[name="code"]');
const password = document.querySelector('.form-item input[name="password"]');
const password_again = document.querySelector('input.password-again');
const agree = document.querySelector('.agree-check .agree');
//用户名验证
function inspect_uname() {
return input_verification(uname, /^\w{4,12}$/g, "4到12位用户名,只能包含数字、字母、下划线") ? true : false;
}
//手机号验证
function inspect_phone() {
return input_verification(phone, /^1[3-9][0-9]{9}$/g, "11位手机号") ? true : false;
}
//检查验证码是否是6位数字
function inspect_code() {
return input_verification(code_input, /^\d{6}$/g, "6位数字验证码") ? true : false;
}
//密码验证,开头必须是字母,6到20位
function inspect_password() {
return input_verification(password, /^(?=.*[a-z])(?=.*\d)[a-z\d]{6,20}$/gi, "6到20位密码,必须包含数字和字母") ? true : false;
}
//验证两次密码输入是否相同
function inspect_password_again() {
let div = password_again.nextElementSibling;
if (password_again.value === password.value) {
div.innerHTML = "";
return true;
} else {
div.innerHTML = "两次密码不一致";
return false;
}
}
// 检查协议是否同意
function inspect_agree() {
let div = agree.nextElementSibling;
if (agree.checked) {
div.innerHTML = "";
return true;
} else {
div.innerHTML = "请同意协议";
return false;
}
}
//监听各个输入框内容是否改变
uname.addEventListener('change', () => {
inspect_uname();
});
phone.addEventListener('change', () => {
inspect_phone();
});
code_input.addEventListener('change', () => {
inspect_code();
});
password.addEventListener('change', () => {
inspect_password();
if (password_again.value) {
inspect_password_again();
}
});
password_again.addEventListener('change', () => {
inspect_password_again();
});
//密码点击查看隐藏
const see_psw = document.querySelectorAll('.form-item .see')
see_psw.forEach((item, index) => {
item.addEventListener('click', () => {
let input = item.parentNode.firstElementChild;
if (input.type === "password") {
item.innerHTML = "隐藏";
input.type = "text";
} else {
item.innerHTML = "显示";
input.type = "password";
}
});
});
//点击提交表单
const btn_submit = document.querySelector('.reg-submit');
const reg_form = document.querySelector('.reg-form');
reg_form.addEventListener('submit', (e) => {
//提交前再次把所有输入框检查一遍
if (!inspect_uname()) { e.preventDefault(); }
if (!inspect_phone()) { e.preventDefault(); }
if (!inspect_code()) { e.preventDefault(); }
if (!inspect_password()) { e.preventDefault(); }
if (!inspect_password_again()) { e.preventDefault(); }
if (!inspect_agree()) { e.preventDefault(); }
})
//初始化函数
function regInit() {
codeInit();
}
//执行初始化
regInit();
</script>
</body>

</html>

登陆界面

登录界面

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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

input {
outline: none;
}

a {
text-decoration: none;
}

.login-box {
margin: 0 auto;
width: auto;
height: auto;
background: rgb(244, 242, 242);
position: absolute;
top: 50%;
left: 50%;
border-radius: 6px;
transform: translate(-50%, -50%);
border: 1px solid #e4e4e4;
}

.login-box .login-title {
width: 100%;
text-align: center;
margin: 12px 0;
font-size: 22px;
font-weight: bolder;
color: #363636;
}

.login-tab {
display: flex;
width: 100%;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
align-content: center;
align-items: center;
user-select: none;
}

.login-tab-line {
width: 1px;
height: 20px;
background: rgb(30, 110, 140);
}

.login-tab-item {
margin: 0px 10px;
transition: all 0.2s;
}

.login-tab-item.active {
color: #4b98db;
}

.login-form {
margin: 10px;
}

.form-item {
display: flex;
position: relative;
width: 300px;
flex-direction: row;
flex-wrap: wrap;
padding-bottom: 25px;
justify-content: space-between;
letter-spacing: 0.6px;
}

.form-item input {
width: 100%;
border: 1px solid #e4e4e4;
height: 40px;
font-size: 16px;
padding: 10px 16px;
border-radius: 6px;
}

.form-item .msg {
position: absolute;
line-height: 1;
width: 100%;
font-size: 12px;
color: rgb(255, 79, 126);
bottom: 9px;
padding-left: 5px;
}

.code-box {
display: flex;
}

.form-item [name="code"] {
flex-shrink: 1;
}

.form-item a.code {
width: fit-content;
height: 40px;
line-height: 40px;
background: rgb(120, 187, 233);
text-align: center;
border-radius: 6px;
color: #fff;
margin-left: 10px;
padding: 0 10px;
flex-shrink: 0;
display: block;
transition: all 0.3s;
user-select: none;
}

.agree-check {
margin: 0 auto;
width: fit-content;
}

.form-item .agree {
width: 20px;
height: 20px;
cursor: pointer;
}

.form-item .agree:checked {
background: #9decbe;
}

.agreement {
width: calc(100% - 20px);
padding-left: 10px;
color: #363636;
line-height: 20px;
height: 20px;
}

.agreement a {
color: #6a9adf;
}

.login-submit {
margin: 0 auto;
display: block;
width: calc(100% - 40px);
height: 40px;
border-radius: 8px;
outline: none;
border: none;
background: #9decbe;
font-size: 18px;
color: #363636;
margin-bottom: 15px;
transition: all 0.3s;
cursor: pointer;
user-select: none;
}

.login-submit:hover {
background: #86ebb0;
}

.form-item .see {
position: absolute;
width: fit-content;
height: auto;
right: 10px;
line-height: 1;
cursor: pointer;
font-size: 14px;
top: 12px;
color: #ababab;
transition: all 0.3s;
user-select: none;
}

.form-item .see:hover {
color: #6a9adf;
}

.login-form {
display: none;
}

.login-form.active {
display: block;
}
</style>
</head>

<body>
<div class="login-box">
<div class="login-title">登陆</div>
<div class="login-tab">
<div class="login-tab-item active" data-id="0">密码登陆</div>
<div class="login-tab-line"></div>
<div class="login-tab-item" data-id="1">短信登陆</div>
</div>
<div class="form-box">
<form class="login-form active">
<div class="form-item">
<input name="uname" type="text" placeholder="用户名 / 手机号" maxlength="13" autocomplete="off" required>
<div class="msg"></div>
</div>
<div class="form-item">
<input name="password" type="password" placeholder="密码" maxlength="20" autocomplete="off" required>
<div class="msg"></div>
<div class="see">显示</div>
</div>
<button class="login-submit">登录</button>
</form>
<form class="login-form">
<div class="form-item">
<input name="phone" type="text" placeholder="输入手机号" maxlength="11" autocomplete="off" required>
<div class="msg"></div>
</div>
<div class="form-item">
<div class="code-box">
<input name="code" type="text" placeholder="输入验证码" maxlength="6" autocomplete="off" required>
<div class="msg"></div>
<a href="javascript:;" class="code">发送验证码</a>
</div>
</div>
<button class="login-submit">登录</button>
</form>
<div class="form-item agree-check">
<input type="checkbox" class="agree" autocomplete="off">
<div class="msg"></div>
<div class="agreement">已阅读并同意<a href="#">《用户协议》</a></div>
</div>
</div>
</div>


<script>
const login_tab = document.querySelector('.login-tab');
const login_form = document.querySelectorAll('.login-form');
const code = document.querySelector('.code-box .code');
const agree = document.querySelector('.agree-check .agree');
const uname = document.querySelector('.form-item input[name="uname"]');
const phone = document.querySelector('.form-item input[name="phone"]');
login_tab.addEventListener('click', (e) => {
let class_name = e.target.className;
if (class_name === 'login-tab-item') {
document.querySelector('.login-tab-item.active').classList.remove('active');
e.target.classList.add('active');
//切换登录方式清空input
document.querySelectorAll('.login-form.active input').forEach((item) => {
item.value = '';
})
document.querySelector('.login-form.active').classList.remove('active');
login_form[e.target.dataset.id].classList.add('active');
}
});
//短信模块
var code_flag = true;//控制点击有没有效果
const codeTime = 30;//验证码发送间隔时间,默认30秒
function codeClick() {
if (code_flag) {
//存入点击发送验证码时的时间戳
localStorage.setItem('code_time', new Date().getTime());
code_flag = false;//可以点击
code_limit_time();
//这里就可以去做请求短信接口
}
}
//验证码间隔验证的初始化
function codeInit() {
//如果验证码间隔倒计时还没30秒,就继续倒计时
let code_time = localStorage.getItem('code_time');
if (code_time) {
let time = codeTime - parseInt((new Date().getTime() - code_time) / 1000);
//小于0说明间隔已经满足
if (time > 0) {
//执行控制验证码间隔函数
code_limit_time(time);
}
}
// 发送短信验证码
code.addEventListener('click', codeClick);
}
// 控制验证码发送间隔函数
function code_limit_time(i = codeTime) {
code.innerHTML = `${i}秒后重新获取`;
code.style.pointerEvents = 'none';
code.style.background = '#c6c6c6';
var stv = setInterval(() => {
i--;
code.innerHTML = `${i}秒后重新获取`;
if (i === 0) {
code_flag = true;
code.innerHTML = `重新获取`;
code.style.pointerEvents = 'auto';
code.style.background = 'rgb(120, 187, 233)';
clearInterval(stv);
//倒计时完成移除时间戳
localStorage.removeItem('code_time');
}
}, 1000)
}
//密码点击查看隐藏
const see_psw = document.querySelector('.form-item .see')
see_psw.addEventListener('click', () => {
let input = see_psw.parentNode.firstElementChild;
if (input.type === "password") {
see_psw.innerHTML = "隐藏";
input.type = "text";
} else {
see_psw.innerHTML = "显示";
input.type = "password";
}
});
// 检查协议是否同意
function inspect_agree() {
console.log(11);
let div = agree.nextElementSibling;
if (agree.checked) {
div.innerHTML = "";
return true;
} else {
div.innerHTML = "请同意协议";
return false;
}
}
function subInit() {
login_form.forEach((item, index) => {
item.addEventListener('submit', (e) => {
e.preventDefault();
if (!inspect_agree()) {
return;
}
//存储用户名或手机号
localStorage.setItem('user', uname.value||phone.value);
//这里作跳转
// location.href = '/'
});
})
}
//初始化函数
function loginInit() {
codeInit();
subInit();
}
//执行初始化
loginInit();
</script>
</body>
</html>