一、知识点回顾
1. flex : 1 -> flex: 1 1 auto ; ( flex-grow ; flex-shrink ; flex-basis)
2. 数组转字符串 join()
3. 字符串转数组 split()
4. 获取年 getFullYear()
5. 月份推到下个月 setDate(32-58)
setDate(1-28) setMonth(getMonth()+1)
存在bug setMonth(getMonth()+1)
1.31->2.31->3.3
6. 月份推到上个月 setDate(0/-1/-2/../-28)
setDate(1-28) setMonth(getMonth()-1)
本月的天数 setDate(32) setDate(0)
先推到下个月 再回到这个月
7. 定时器的语法 setInterval(fn,time,第一个函数的参数)
8. 截取字符串的方法 slice(i,i) substr(i,n) substrig(i,i)
9. 对象的深拷贝
var obj = {}
var obj2 = {}
遍历obj for in
10. 基本数据类型和引用数据类型的区别
基本数据类型存储的是值
引用数据类型存储的是地址
二、注册验证
思路:1. 封装rand get 验证码函数
2. 通过get方法拿到需要的对象 例如:var oUser = get('user');
3. 创建四个数组
4. 绑定点击事件->验证码刷新
5. 第一次打开时网页就有显示 get('code').innerHTML = randCode()
6. 绑定点击事件->验证
6.1 用户名验证
6.11 去掉首尾空格 var username = oUser.value.trim()
6.12 判断为空
6.13 验证长度 (长度必须在3-6位之内)
6.14 验证数字(不能以数字开头) if(numArr.includes(username.charAt(0)))
6.15 验证非法字符(不能包含非法字符)if(! allArr.includes(username[i]))
6.16 用户名验证成功 oUserSpan.innerHTML = '√'
6.2 密码验证
6.21 去掉首尾空格 var password = oPwd.value.trim()
6.22 判断为空
6.23 验证长度(长度必须在3-6位之内)
6.24 验证非法字符(不能包含非法字符)
6.25 强度验证 纯数字,字母,则弱;任意两种,则中;大写字母合小写
字母结合数字,则强
6.26 密码验证成功 oPwdSpan.innerHTML = '√'
6.3 验证码验证
6.31 获取输入框的值 获取验证码的值
6.32 判断两值是否相等(验证码不分大小写)
相等 -> 验证通过
不相等 -> 验证码重新刷新 输入框清空
验证失败
7.用户名 密码 验证码 三者全部成功,则注册成功
<script>
function rand(max,min) {
min = min || 0
return parseInt(Math.random()*(max - min)+ min )
}
function get(id) {
return document.getElementById(id)
}
// 拿对象
var oUser = get('user');
var oUserSpan = get('userSpan');
var oPwd = get('pwd')
var oPwdSpan = get('pwdSpan')
var oCode = get('code')
var oCodeSpan = get('codeSpan')
var oMsg = get('msg')
var oBtn = get('btn')
var oStrong = get('strong')
var numArr = [];
for(var i = 0 ; i < 10 ; i++){
numArr.push(i + '')
}
var smallArr = [];
for(var i = 97 ; i<= 122 ; i++){
smallArr.push(String.fromCharCode(i))
}
var bigArr = [];
for(var i = 65 ; i <= 90 ; i++){
bigArr.push(String.fromCharCode(i))
}
var allArr = numArr.concat(smallArr , bigArr);
function randCode(n) {
n = n || 4 ;
var res = '' ;
res += numArr[rand(numArr.length)];
res += smallArr[rand(smallArr.length)];
res += bigArr[rand(bigArr.length)];
for(var i = 0 ; i < n - 3 ; i++){
res += allArr[rand(allArr.length)];
}
// 把字符串转数组
var arr = res.split('')
// 交换位置
for(var i in arr ){
var index = rand(arr.length)
var t = arr[i] ;
arr[i] = arr[index]
arr[index] = t ;
}
res = arr.join('')
return res
}
oCodeSpan.innerHTML = randCode()
oCodeSpan.onclick = function () {
oCodeSpan.innerHTML = randCode()
}
function tips(obj , msg , color) {
obj.innerHTML = msg ;
obj.style.color = color ;
}
// 验证
oBtn.onclick = function () {
// 去掉用户名首尾空格
var username = oUser.value.trim() ;
// 判断为空
if(username === ''){
tips(oUserSpan,"输入不能为空",'red');
return
}
// 判断长度
if(username.length < 3 || username.length > 6){
tips(oUserSpan,'长度必须在3-6位之间',"red")
return
}
// 判断是否数字开头
if(numArr.includes(username[0])){
tips(oUserSpan,'不能用数字开头','red');
return
}
// 必须是字母,数字组成
for(var i in username){
if(!allArr.includes(username[0])){
tips(oUserSpan,'用户名只能是字母和数字','red');
return
}
}
tips(oUserSpan,'√','green')
// 判断密码
// 去掉密码首尾空格
var password = oPwd.value.trim();
// 判断为空
if(password === ''){
tips(oPwdSpan,'输入不能为空','red');
return
}
// 判断长度
if(password.length < 3 || password.length > 6){
tips(oPwdSpan,'长度必须在3-6位之内','red')
return
}
// 必须是字母,数字组成
for(var i in password){
if(!allArr.includes(password[0])){
tips(oPwdSpan,'密码必须在3-6位之间','red')
return
}
}
// 强度验证
var count1 = 0 ; // 数字
var count2 = 0 ; // 小写
var count3 = 0 ; // 大写
for(var i in password){
if(numArr.includes(password[i])){
count1 = 1
}
if(smallArr.includes(password[i])){
count2 = 1
}
if(bigArr.includes(password[i])){
count3 = 1
}
}
var count = count1 + count2 + count3
if(count === 1){
tips(oStrong,'弱','red')
}
if(count === 2){
tips(oStrong,'中','yellow')
}
if(count === 3){
tips(oStrong,'强','green')
}
tips(oPwdSpan,'√','green')
//验证码
var str = oCode.value
var str2 = oCodeSpan.innerHTML
if(str.toLowerCase() === str2.toLowerCase()){
oMsg.innerHTML = '验证通过'
oMsg.style.color = 'green'
}else{
oCodeSpan.innerHTML = randCode();
oCode.value = '' ;
oMsg.innerHTML = '验证失败'
oMsg.style.color = 'red'
}
alert('注册成功')
}
</script>
</body>
三、定时器
定时器
语法 : setInterval(fn,time)
变量存储的是一个数字(页面中的第几个定时器)
定时器是异步的
清除定时器 clearInterval(第几个定时器)
js 单线程的语言
代码正常从上往下执行
但是有一些特殊的功能:异步
图片的请求,数据的请求 -- 需要服务器响应(需要时间的)
定时器和延时器以及点击事件 -- 不是立即执行的(需要时间的,或者需要用户)
js 的所有代码都在主线程上执行
同步先执行
异步存放在任务队列中(任务队列不能执行任务,而是任务到时间了之后去主线程上执行)
var t = setInterval(function(){
console.log(666);
},1000)
console.log(1);
// clearInterval(t) 清空计时器
四、倒计时
<h1 id="h"></h1>
<script>
var oH1 = document.getElementById('h');
var count = 10 ;
oH1.innerHTML = count + 's';
var t = setInterval(function(){
count--
oH1.innerHTML = count + 's';
if(count === 0){
clearInterval(t)
}
},1000)
</script>
五、按钮倒计时
思路:
一、1个按钮控制开和关
1. 首先获取元素
2. 绑定点击事件
2.1 if判断,若按钮开启,则定时器开始运行,按钮变成暂停
2.2 否则清空定时器,按钮回到开始
二、1个按钮控制开和暂停
1. 绑定点击事件
1.1 按钮点击时,计时器清空,计时器开始 。 (这样能实现每次点击是暂停,第
二次点击是继续的效果)
三、3个按钮分别控制开,暂停,结束
1. 绑定开始按钮点击事件
1.1 一旦点击开始按钮,开始按钮禁用,暂停和结束按钮开启 计时器开启
2. 绑定暂停按钮点击事件
2.1 一旦点击暂停按钮,清空计时器,暂停按钮禁用,开始按钮开启。
3. 绑定结束按钮点击事件
3.1 一旦点击结束按钮,清空计时器,页面上清回0,结束按钮禁用,暂停按钮禁
用,开始按钮打开
var oBtn = document.getElementById('btn');
var oPause = document.getElementById('pause');
var oEnd = document.getElementById('end')
var oSpan = document.getElementById('span')
// 每次点击的时候都会重新调用这个函数
// 存储定时器的变量必须在点击事件外面声明 -> 也就是说他必须是一个全局变量
// Version 1.0 , 1个按钮控制开关
// var t
// oBtn.onclick = function(){
// if(oBtn.innerHTML === '开始'){
// oBtn.innerHTML = '暂停'
// t = setInterval(function(){
// oSpan.innerHTML++;
// },1000)
// }
// else{
// clearInterval(t)
// oBtn.innerHTML = '开始'
// }
// }
// Version 2.0 , 1个按钮控制开/暂停
// var t ;
// oBtn.onclick = function(){
// clearInterval(t)
// t = setInterval(function(){
// oSpan.innerHTML++
// },1000)
// }
// Version 3.0 , 3个按钮控制开关暂停
var t
oBtn.onclick = function(){
oBtn.disabled = true
oPause.disabled = false
oEnd.disabled = false
t = setInterval(function(){
oSpan.innerHTML++;
},1000)
}
oPause.onclick = function(){
clearInterval(t)
oPause.disabled = true
oBtn.disabled = false ;
}
oEnd.onclick = function(){
clearInterval(t)
oSpan.innerHTML = 0
oEnd.disabled = true
oPause.disabled = true
oBtn.disabled = false ;
}
六、小广告
思路:右下角出现弹窗小广告
1. get方法获取元素
2. 10s倒计时后关闭
2.1 设置定时器 倒计时在减小 oTime.innerHTML--
2.2 判断时间<0 ,则关闭 -> display:none,随后清空计时器
3. 点X关闭
3.1 绑定点击事件 点击,则关闭 -> display.none,随后清空计时器
<script>
// 右下角出现弹窗
var oAd = document.getElementById('ad')
var oClose = document.getElementById('close')
var oTime = document.getElementById('time')
// 10s 倒计时后关
var t = setInterval(function(){
oTime.innerHTML--;
if(oTime.innerHTML < 0 ){
oAd.style.display = 'none';
clearInterval(t);
}
},500)
// 点X关
oClose.onclick = function(){
oAd.style.display = 'none';
clearInterval(t);
}
</script>
七、延时器
定时器:重复的闹钟
延时器:一次性的闹钟
setTimeout(fn,time)
变量存储的是第几个闹钟(不分定时器和延时器)
setTimeout也是异步
clearInterval 可以清除定时器,也可以清除延时器
clearTimeout 可以清除延时器,也可以清除定时器
var t1 = setInterval(function(){
console.log(777);
},1000)
var t2 = setTimeout(function(){
console.log(666);
},0)
console.log(t1 , t2);
// clearInterval(t1)
// // clearTimeout(t2)
// clearTimeout(t1)
// clearInterval(t2)
八、关于异步
异步:
在点击事件里面,绑定是同步的,事件处理函数是异步的
在定时器里面,要做的事情是异步的
var t = setTimeout(function(){},1000)
clearInterval(t)
var oH1 = document.getElementById('h');
oH1.onclick = function(){
console.log(666);
}
九、延时器改定时器
延时器:只会执行一次
死递归:短时间内内存溢出(递归一定要有结束的条件)
// 延时器:只会执行一次
// setTimeout(function(){
// console.log(666);
// },1000)
// 死递归:短时间内内存溢出(递归一定要有结束的条件)
// 每隔1s调用函数
function fn(){
setTimeout(function(){
console.log(666);
fn()
},1000)
}
fn()
// 递归
十、流氓小广告
思路:用延时器 倒计时结束后,广告再出现在页面中;关闭广告后,广告再出现在页面中;
1. get方法获取元素的值
2. 封装showAd函数
2.1 设置延时器 3s后,打开广告(广告默认是关闭的 display:none)
2.2 10s后自动关闭
2.21 设置定时器
2.22 时间-- 时间<0 则关闭,清空定时器,时间回到10,调用一次showAd()
2.3 点X关闭
2.31 绑定点击事件 点击X关闭 ,计时器清空,时间回到10,调用一次
showAd()
var oAd = document.getElementById('ad')
var oClose = document.getElementById('close')
var oTime = document.getElementById('time')
function showAd(){
setTimeout(function(){
oAd.style.display = 'block'
// 10s 倒计时后关
var t = setInterval(function(){
oTime.innerHTML--;
if(oTime.innerHTML < 0 ){
oAd.style.display = 'none';
clearInterval(t);
oTime.innerHTML = 10;
showAd()
}},500)
// 点X关
oClose.onclick = function(){
oAd.style.display = 'none';
clearInterval(t);
oTime.innerHTML = 10;
showAd()
}
},3000)
}
showAd()
十一、日历
日历分析:
上个月 + 本月 + 下个月 = 42
上个月 显示几天是由本月的第一天是星期几来决定的
本月 所有的天数
下个月 下个月 42 - 上个月的天数 - 本月的天数
思路:
1.实现封装函数
1.1 封装本月的天数
1.10 先创建当前时间 var date = new Date(time)
1.11 把日期推到下个月 date.setDate(32)
1.12 把日期推到这个月 date.setDate(0)
1.13 设置 var maxDay = date.getDate()
1.14 把数据放入数组中 for(i = 1 ; i <= maxDay ; i++) list.push(i)
1.2 封装上个月的天数
// 注意:观察日历得知:本月的第一天是星期几能决定上个月显示几天
1.20 先创建当前时间 var date = new Date(time)
1.21 获取本月的第一天是星期几 date.setDate(1) var week = date.getDay()
1.22 if(week === 0){week = 7}
1.23 把日期推到第0天 date.setDate(0)
1.24 设置 var maxDay = date.getDate()
1.25 把数据放入数组中 for(i = maxDay - week + 2 ; i <= maxDay ; i++)
list.push(i)
1.3 拼接上个月的天数
1.31 var prevDays = getPrevDays(date);
1.32 prevDays.forEach(function(v) { res += `<li style = 'color:#666;'>${v}</li>` })
1.4 拼接本月的天数
1.41 var nowDays = getNowDays(date);
1.42 nowDays.forEach(function(v) { res += `<li >${v}</li>` })
1.5 拼接下个月的天数
1.51 for(var i = 1 ; i <= 42 - prevDays.length - nowDays.length ; i++)
1.52 { res += `<li style = 'color:#666;'>${i}</li>` })
2.下翻页:日期推到下个月
2.1 date.setDate(32); getList()
3.上翻页:日期推到上个月
3.1 date.setDate(0); getList()
var oList = document.getElementById('list');
var oPrev = document.getElementById('prev');
var oNext = document.getElementById('next');
var date = new Date()
getList()
// 下翻页:日期推到下个月
oNext.onclick = function () {
date.setDate(32);
getList()
}
// 上翻页:日期推到上个月
oPrev.onclick = function () {
date.setDate(0);
getList()
}
function getList() {
var res = '';
// 拼接上个月的天数
var prevDays = getPrevDays(date);
prevDays.forEach(function(v) {
res += `<li style = 'color:#666;'>${v}</li>`
})
// for(var i = 0 ; i < prevDays.length ; i++){
// res += `<li>${prevDays[i]}</li>`
// }
// 拼接本月的天数
var nowDays = getNowDays(date);
nowDays.forEach(function (v) {
res += `<li>${v}</li>`
})
// for(var i = 0 ; i < nowDays.length ; i++){
// res += `<li>${nowDays[i]}</li>`
// }
// 拼接下一个月的天数
for(var i = 1 ; i <= 42 - prevDays.length - nowDays.length ; i++){
res +=`<li style = 'color:#666;'>${i}</li>`
}
oList.innerHTML = res
}
// 获取本月的天数
function getNowDays(time) {
var date = new Date(time);
// 把日期推到下个月
date.setDate(32);
// 把日期推动本月
date.setDate(0);
var maxDay = date.getDate();
var list = []
for(i = 1 ; i <= maxDay ; i++){
list.push(i)
}
return list
}
// 获取上个月的天数
// 注意:观察日历得知:本月的第一天是星期几能决定上个月显示几天
function getPrevDays(time) {
var date = new Date(time);
// 先获取本月的第一天是星期几
date.setDate(1)
var week = date.getDay();
if(week === 0) {
week = 7
}
// 把日期推到第0天
date.setDate(0);
var maxDay = date.getDate();
var list = []
for(i = maxDay - week + 2 ; i <= maxDay ; i++){
list.push(i)
}
return list
}
效果图: