获取时间对象的方法:
<html lang="en">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Document
div {
width: 400px;
height: 50px;
background-color: pink;
text-align: center;
line-height: 50px;
}
let arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
let div = document.querySelector('div')
// 先调用,就省去了1秒的空白期
getTime()
setInterval(getTime, 1000)
function getTime() {
// 1. 实例化时间对象 一定写到定时器里面才可以
let date = new Date() //获得当前时间
let year = date.getFullYear()
let month = date.getMonth() + 1 //获得月份 因为是数组下标值0-11,得在后面加1
let date1 = date.getDate() //今天是一个月的几号?
let hour = date.getHours()
let min = date.getMinutes()
let sec = date.getSeconds()
let day = date.getDay() //获取星期
div.innerHTML = `今天是: ${year}年${month}月${date1}日 ${hour}:${min}:${sec} ${arr[day]}`
}
5.2 时间戳和大小写
时间戳:指从1970年1月1日00:00:00到现在的微秒数。 这是一种特殊的时间测量方法
获取时间戳的三种方法:
1.使用getTime()方法
let date = new Data();
console.log(date.getTime);
1.缩写+newDate()
console.log(+new Date());
console.log(+new Date('2022-8-30 12:00:00')) // 指定时间的时间戳
1.使用Date().now:不需要实例化,只能获取当前时间戳,而上面两个可以返回指定时间的时间戳
console.log(Date.now());
<html lang="en">
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
Document
.countdown {
width: 240px;
height: 305px;
text-align: center;
line-height: 1;
color: #fff;
background-color: brown;
/* background-size: 240px; */
/* float: left; */
overflow: hidden;
}
.countdown .next {
font-size: 16px;
margin: 25px 0 14px;
}
.countdown .title {
font-size: 33px;
}
.countdown .tips {
margin-top: 80px;
font-size: 23px;
}
.countdown small {
font-size: 17px;
}
.countdown .clock {
width: 142px;
margin: 18px auto 0;
overflow: hidden;
}
.countdown .clock span,
.countdown .clock i {
display: block;
text-align: center;
line-height: 34px;
font-size: 23px;
float: left;
}
.countdown .clock span {
width: 34px;
height: 34px;
border-radius: 2px;
background-color: #303430;
}
.countdown .clock i {
width: 20px;
font-style: normal;
}
<div class="countdown">
<p class="next">今天是2021年8月28日
<p class="title">下班倒计时
<p class="clock">
<span id="hour">00
:
<span id="minutes">25
:
<span id="scond">20
<p class="tips">
现在是18:30:00
let divNext = document.querySelector('.countdown .next');
let divTips = document.querySelector('.countdown .tips');
let hours = document.querySelector('#hour');
let minutes = document.querySelector('#minutes');
let secs = document.querySelector('#scond');
let endTime = +new Date('2022-8-31 18:00-00');
let timeClock = 0;
let h = 0 ;
let m = 0 ;
let ss = 0;
getTimeSS();
function getTimeSS() {
let date = new Date()
let year = date.getFullYear();
let month = date.getMonth() + 1 ; //获得月份 因为是数组下标值0-11,得在后面加1
let date1 = date.getDate(); //今天是一个月的几号?
let hour = date.getHours();
hour = hour < 10 ? '0' + hour :hour;
let min = date.getMinutes();
min = min < 10 ? '0' + min :min;
let sec = date.getSeconds();
sec = sec < 10 ? '0' + sec :sec;
let day = date.getDay();
divNext.innerHTML = `今天是: ${year}年${month}月${date1}日` ;
divTips.innerHTML = `现在是 ${hour}:${min}:${sec}`
let nowTime = +new Date();
timeClock = (endTime - nowTime) / 1000;
h =parseInt(timeClock /60 /60 %24);
h = h <10 ? '0'+h : h ;
m = parseInt(timeClock /60 %60);
m = m < 10 ? '0' + m : m ;
ss =parseInt(timeClock %60);
ss = ss <10 ? '0' +ss : ss;
hours.innerHTML = h;
minutes.innerHTML = m;
secs.innerHTML = ss;
}
setInterval(getTimeSS,1000);
5.3 案例-微博发布
<html lang="en">
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
微博发布
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
.w {
width: 900px;
margin: 0 auto;
}
.controls textarea {
width: 878px;
height: 100px;
resize: none;
border-radius: 10px;
outline: none;
padding-left: 20px;
padding-top: 10px;
font-size: 18px;
}
.controls {
overflow: hidden;
}
.controls div {
float: right;
}
.controls div span {
color: #666;
}
.controls div .useCount {
color: red;
}
.controls div button {
width: 100px;
outline: none;
border: none;
background: rgb(0, 132, 255);
height: 30px;
cursor: pointer;
color: #fff;
font: bold 14px '宋体';
transition: all 0.5s;
}
.controls div button:hover {
background: rgb(0, 225, 255);
}
.controls div button:disabled {
background: rgba(0, 225, 255, 0.5);
}
.contentList {
margin-top: 50px;
}
.contentList li {
padding: 20px 0;
border-bottom: 1px dashed #ccc;
position: relative;
}
.contentList li .info {
position: relative;
}
.contentList li .info span {
position: absolute;
top: 15px;
left: 100px;
font: bold 16px '宋体';
}
.contentList li .info p {
position: absolute;
top: 40px;
left: 100px;
color: #aaa;
font-size: 12px;
}
.contentList img {
width: 80px;
border-radius: 50%;
}
.contentList li .content {
padding-left: 100px;
color: #666;
word-break: break-all;
}
.contentList li .the_del {
position: absolute;
right: 0;
top: 0;
font-size: 28px;
cursor: pointer;
}
<div class="w">
<div class="controls">
src="./images/9.6/tip.png" alt="" /><br />
<textarea placeholder="说点什么吧..." id="area" cols="30" rows="10" maxlength="200">
<span class="useCount" id="useCount">0
/
200
<button id="send">发布
<div class="contentList">
<ul id="list">
<li hidden>
<div class="info">
class="userpic" src="./images/9.6/03.jpg" />
<span class="username">死数据:百里守约
<p class="send-time">死数据:发布于 2020年12月05日 00:07:54
<div class="content">死数据:111
<span class="the_del">X
// maxlength 是一个表单属性, 作用是给表单设置一个最大长度
// 模拟数据
let dataArr = [
{ uname: '司马懿', imgSrc: './images/9.5/01.jpg' },
{ uname: '女娲', imgSrc: './images/9.5/02.jpg' },
{ uname: '百里守约', imgSrc: './images/9.5/03.jpg' },
{ uname: '亚瑟', imgSrc: './images/9.5/04.jpg' },
{ uname: '虞姬', imgSrc: './images/9.5/05.jpg' },
{ uname: '张良', imgSrc: './images/9.5/06.jpg' },
{ uname: '安其拉', imgSrc: './images/9.5/07.jpg' },
{ uname: '李白', imgSrc: './images/9.5/08.jpg' },
{ uname: '阿珂', imgSrc: './images/9.5/09.jpg' },
{ uname: '墨子', imgSrc: './images/9.5/10.jpg' },
{ uname: '鲁班', imgSrc: './images/9.5/11.jpg' },
{ uname: '嬴政', imgSrc: './images/9.5/12.jpg' },
{ uname: '孙膑', imgSrc: './images/9.5/13.jpg' },
{ uname: '周瑜', imgSrc: './images/9.5/14.jpg' },
{ uname: '老夫子', imgSrc: './images/9.5/15.jpg' },
{ uname: '狄仁杰', imgSrc: './images/9.5/16.jpg' },
{ uname: '扁鹊', imgSrc: './images/9.5/17.jpg' },
{ uname: '马可波罗', imgSrc: './images/9.5/18.jpg' },
{ uname: '露娜', imgSrc: './images/9.5/19.jpg' },
{ uname: '孙悟空', imgSrc: './images/9.5/20.jpg' },
{ uname: '黄忠', imgSrc: './images/9.5/21.jpg' },
{ uname: '百里玄策', imgSrc: './images/9.5/22.jpg' },
]
// 需求1
// 1. 注册input事件
// 2. 将文本的内容的长度赋值给对应的数值
// 3. 表单的maxlength属性可以直接限制在200个数之间
let textarea = document.querySelector('textarea');
let useCount = document.querySelector('.useCount');
// 发布按钮
let send = document.querySelector(`#send`)
// 获取ul
let ul = document.querySelector('#list');
textarea.addEventListener('input',function (){
// console.log(this.value.length);
useCount.innerHTML = this.value.length;
if (this.value.length > 200){
send.disabled = true;
}
})
// 需求2
//点击按钮之后判断
// 克隆预定义好的模板,将模板的hidden属性设置为false, 并最终展示到页面上
// 判断如果内容为空,则提示不能输入为空, 并且直接return
// 防止输入无意义空格, 使用字符串.trim()去掉首尾空格, 并将表单的value值设置为空字符串
send.addEventListener('click' , function () {
if(textarea.value.trim() ===''){ //字符串.trim()去掉首尾空格
textarea.value = '';
useCount.innerHTML = 0;
return alert('输入内容为空');
}
// 需求3
// 获取文本域的内容, 赋值给由模板克隆出来的新标签里面的content.innerText
// 随机获取数据数组里面的内容, 替换newNode的图片和名称
// 利用时间对象将时间动态化 new Date().toLocaleString()
//创建一个li
let li = document.createElement('li');
//随机数
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
let random = getRandom(0, dataArr.length - 1)
//追加内容到li里边
li.innerHTML = `
<div class="info">
class="userpic" src=${dataArr[random].imgSrc} >
<span class="username">${dataArr[random].uname}
<p class="send-time">${new Date().toLocaleString()}
<div class="content">${textarea.value}
<span class="the_del">X
`;
// 需求4
// 在事件处理函数里面获取点击按钮,注册点击事件
// (易错点: 必须在点击事件内里面获取,外面获取不到)
// 删除对应的元素 (通过this获取对应的那条需要删除的元素)
// 教你一招: 放到追加进ul的前面,这样创建元素的同时顺便绑定了事件,赞~~
// 使用 li.querySelector() 找到li元素
let del = li.querySelector('.the_del');
del.addEventListener('click',function () {
//删除操作
ul.removeChild(li);
})
//追加li节点
ul.insertBefore(li,ul.children[0]);
//需求5
// 将表单域内容重置为空
// 将userCount里面的内容重置为0
textarea.value = '';
useCount.innerHTML = 0;
})
5.4 重画和重新排列
重绘不一定会引起回流,而回流一定会引起重绘。
回流(重排)
当RenderTree中部分或全部元素的规格、结构和布局发生变化时,浏览器将重新渲染部分或全部文档,这称为回流。
导致回流(重排)的操作:
• 页面第一次刷新 • 浏览器窗口大小变化 • 元素大小或位置变化 • 字体大小变化 • 内容变化(如:输入框的输入、大小图片的) • 激活CSS伪类(例如::hover) • DOM的脚本操作(添加或删除可见的DOM元素)
简单理解影响布局,会出现回流
重画
由于节点(元素)样式的改变不会影响其在文档流和文档布局中的位置(例如:颜色、背景颜色、轮廓等),因此称为重绘。
5.5 案例购物车
<html lang="en">
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
购物车全选功能
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
a {
text-decoration: none;
color: #666;
}
body {
background: #fff;
color: #666;
font-size: 14px;
}
input {
outline: none;
}
.clearfix::before,
.clearfix::after {
content: '';
display: block;
clear: both;
}
.clearfix {
*zoom: 1;
}
table {
width: 800px;
margin: 0 auto;
border-collapse: collapse;
}
th {
font: normal 14px/50px '宋体';
color: #666;
}
th,
td {
border: none;
text-align: center;
border-bottom: 1px dashed #ccc;
}
input[type='checkbox'] {
width: 13px;
height: 13px;
}
tbody p {
position: relative;
bottom: 10px;
}
tbody .add,
tbody .reduce {
float: left;
width: 22px;
height: 22px;
border: 1px solid #ccc;
text-align: center;
background: none;
outline: none;
cursor: pointer;
}
tbody input[type='text'] {
width: 50px;
float: left;
height: 18px;
text-align: center;
}
tbody .count-c {
width: 98px;
margin: 0 auto;
}
button[disabled] {
color: #ddd;
cursor: not-allowed;
}
tbody tr:hover {
background: #eee;
}
tbody tr.active {
background: rgba(241, 209, 149, 0.945);
}
.controls {
width: 790px;
margin: 10px auto;
border: 1px solid #ccc;
line-height: 50px;
padding-left: 10px;
position: relative;
}
.controls .del-all,
.controls .clear {
float: left;
margin-right: 50px;
}
.controls p {
float: right;
margin-right: 100px;
}
.controls span {
color: red;
}
.controls .pay {
position: absolute;
right: 0;
width: 80px;
height: 54px;
background: red;
font: bold 20px/54px '宋体';
color: #fff;
text-align: center;
bottom: -1px;
}
.controls .total-price {
font-weight: bold;
}
<div class="car">
<input type="checkbox" id="all" />全选 |
商品 |
单价 |
商品数量 |
小计 |
操作 |
<tbody id="carBody">
<input class="s_ck" type="checkbox" readonly /> |
src="./images/01.jpg" /> 牛奶 |
<td class="price">5¥
<div class="count-c clearfix"> <button class="reduce" disabled>- <input type="text" value="1" /> <button class="add">+ |
<td class="total">5¥
<a href="javascript:" class="del">删除 |
<input class="s_ck" type="checkbox" /> |
src="./images/01.jpg" /> 牛奶 |
<td class="price">10¥
<div class="count-c clearfix"> <button class="reduce" disabled>- <input type="text" value="1" /> <button class="add">+ |
<td class="total">20¥
<a href="javascript:" class="del">删除 |
<input class="s_ck" type="checkbox" /> |
src="./images/01.jpg" /> 牛奶 |
<td class="price">30¥
<div class="count-c clearfix"> <button class="reduce" disabled>- <input type="text" value="1" /> <button class="add">+ |
<td class="total">20¥
<a href="javascript:" class="del">删除 |
<input class="s_ck" type="checkbox" /> |
src="./images/01.jpg" /> 牛奶 |
<td class="price">35¥
<div class="count-c clearfix"> <button class="reduce" disabled>- <input type="text" value="1" /> <button class="add">+ |
<td class="total">35¥
<a href="javascript:" class="del">删除 |
<div class="controls clearfix">
<a href="javascript:" class="del-all">删除所选商品
<a href="javascript:" class="clear">清理购物车
<a href="javascript:" class="pay">去结算
已经选中<span id="totalCount">0</span>件商品;总价:0¥</span>
// + - 删除是相同的,一一对应的,我们完全可以用一个for 来遍历规律
let adds = document.querySelectorAll('.add');
let reduce = document.querySelectorAll('.reduce');
let del = document.querySelectorAll('.del');
let prices = document.querySelectorAll('.price');
let totals = document.querySelectorAll('.total')
let totalPrice = document.querySelector('.total-price');
let totalCount = document.querySelector('#totalCount');
let carBody = document.querySelector('#carBody');
//获取输入框
let inputs = document.querySelectorAll('.count-c input');
for (let i = 0; i < adds.length; i++) {
totals[i].innerText = prices[i].innerText;
result();
//加号
adds[i].addEventListener('click',function () {
// alert('1');
inputs[i].value++;
reduce[i].disabled = false;
//计算小计模块
totals[i].innerText = parseInt(prices[i].innerText) * inputs[i].value + '¥';
//计算总额
result();
})
//减号
reduce[i].addEventListener('click',function () {
// alert('1');
inputs[i].value--;
//如果小于等于1 disable = true
if (inputs[i].value <= 1){
reduce[i].disabled = true;
}
//计算小计模块
totals[i].innerText = parseInt(prices[i].innerText) * inputs[i].value + '¥';
//计算总额
result();
})
//删除操作
del[i].addEventListener('click',function () {
carBody.removeChild(this.parentNode.parentNode);
//重新调用统计模块
result();
})
}
//计算总价格
function result() {
totals = document.querySelectorAll('.total');
inputs = document.querySelectorAll('.count-c input');
let sum = 0;
let num = 0;
for (let i = 0; i < totals.length; i++) {
sum = sum + parseInt(totals[i].innerText);
num = num + +inputs[i].value ;
// console.log(sum);
}
totalPrice.innerText = sum + '¥';
totalCount.innerText = num;
}
//div span ul li 标签 有文字内容 怎么得到或则设置文字内容呢, 元素.innerText 元素.innerHtml
//表单 input 单选 复选 textarea select 怎么得到或设置值 表单的value
//特殊的 button 是通过inner来设置
6. 事件对象和属性 6.1 Storm 对象 e
风暴对象也是一个对象,这个对象在风暴触发时有相关信息
如何获得:
1.storm绑定的反弹函数第一个参数是storm对象 2.通常命名为event,ev,e
元素.addEventListener('click',function(e){
console.log(e);
})
Storm对象的一些常用属性:
•type•获取当前风暴类型•clientX/clientY•获取光标相对于浏览器可见窗口左上角的位置•pageX/pageY•获取当前浏览器页面的左上角位置window •offsetX/offsetY•获取光标相对于当前DOM元素左上角的位置 key•用户按下的键的值•目前不推荐使用keyCode•e。 PreventDefault() 防止风暴的默认行为
document.addEventListener('click', function (e) {
// console.log(11)
// pageX 和 pageY 跟文档坐标有关系
// console.log(e)
console.log('clientX:' + e.clientX, 'clientY:' + e.clientY) //可见区域坐标
console.log('pageX:' + e.pageX, 'pageY:' + e.pageY) //
console.log('offsetX:' + e.offsetX, 'offsetY:' + e.offsetY) //当前文档坐标
})
案件:
需求:一张图片仍然与键盘连接分析:①:键盘在页面中连接,使用mousemove②:只要不断将键盘在页面中的坐标位置赋给图片的left和top值即可。
<html lang="en">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Document
img {
position: absolute;
top: 0;
left: 0;
}
src="./images/tianshi.gif" alt="">
let img = document.querySelector('img');
document.addEventListener('mousemove',function (e) {
img.style.left = e.clientX -30 +'px';
img.style.top = e.clientY -40 +'px';
})
查看微博并按Enter键发布
textarea.addEventListener('keyup',function (e) {
// console.log(e.key) 通过这个来检测回车键
if (e.key == 'Enter'){
//自动出发 点击按钮发送事件
send.click();
}
案例:选中复选框是单击复选框 e.preventDefault() 的默认行为。 下面的反例展示了如何防止默认行为:
Please click on the checkbox control.
<label for="id-checkbox">Checkbox:
<input type="checkbox" id="id-checkbox"/>
<div id="output-box">
document.querySelector("#id-checkbox").addEventListener("click", function(e) {
document.getElementById("output-box").innerHTML += "Sorry! preventDefault()
won't let you check this!
";
e.preventDefault();
}, false);
6.2 风暴流
风暴流是指风暴完整执行过程中的流程路径
图像
说明:假设页面中有一个div。 风暴触发时会经历两个阶段,即捕获阶段和冒泡阶段。 简单来说:捕获阶段是从父级到子级,冒泡阶段是从子级到父级。
风暴冒泡的概念:当某个元素的风暴被触发时,该元素的所有祖先元素中都会依次触发相同的风暴。 这个过程称为冒泡。简单理解:当某个元素触发风暴时,会依次调用所有父元素
同名风暴
。 默认情况下存在风暴冒泡。
阻止风暴流
由于冒泡模式默认存在,很容易造成干扰,影响父元素
如果风暴仅限于当前元素,则需要阻止风暴流动
要停止风暴活动,需要获取风暴的对象
句型:storm object.stopPropagation() e.stopPropagation()
此方法可以阻挡风浪流的传播,不仅在冒泡阶段有效,在捕获阶段也有效
<html lang="en">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Document
.father {
margin: 100px auto;
width: 500px;
height: 500px;
background-color: pink;
}
.son {
width: 200px;
height: 200px;
background-color: purple;
}
<div class="father">
<div class="son">
let fa = document.querySelector('.father')
let son = document.querySelector('.son')
fa.addEventListener('click', function (e) {
alert('我是爸爸')
e.stopPropagation()
})
son.addEventListener('click', function (e) {
alert('我是儿子')
// 阻止流动 Propagation 传播
e.stopPropagation()
})
document.addEventListener('click', function () {
alert('我是爷爷')
})
// btn.onclick = function() {}
键盘的扩展经历了风雨:
Ømouseover和mouseout会有冒泡效果
Ømouseenter和mouseleave没有冒泡效果(推荐)
阻止默认行为,如链接点击不跳转、表单字段跳转:e.preventDefault()
<a href="http://www.baidu.com">跳转到百度
let a = document.querySelector('a')
a.addEventListener('click', function (e) {
// 阻止默认行为 方法
e.preventDefault() //a标签就不会跳转。这个可以用于一些条件判断和流程控制等应用
})
两次注册风暴的区别
传统注册 (L0)
Ø对于同一个对象,之前注册的storm会覆盖上面的注册(同一个storm)Ø直接使用null覆盖pair来解除storm的绑定Ø都是在冒泡阶段执行
风暴窃听注册(L2)
• Ø 语句模式:addEventListener(事件类型、事件处理函数、是否使用捕获) • Ø 之前注册的事件不会覆盖上面注册的事件(同一事件) • Ø 第三个参数可以用来判断是否是冒泡或捕获阶段执行• Ø 必须使用removeEventListener(风暴类型,风暴处理函数,获取捕获或冒泡阶段) Ø 匿名函数很难解绑
点击
let btn = document.querySelector('button')
// 1.l0 on
// 多次相同的事件,只执行最后一次
// btn.onclick = function () {
// alert('第一次')
// }
// btn.onclick = function () {
// alert('第二次')
// }
// 解绑事件
// btn.onclick = null
// 2. addEventListener
btn.addEventListener('click', add)
function add() {
alert('第一次')
}
// btn.addEventListener('click', function () {
// alert('第二次')
// })
btn.removeEventListener('click', add) //解绑事件。移除某事件的绑定的方法
6.3 风暴委托
风波流是借助风波流的特点来解决一些开发需求的知识方法
总结:
Ø优点:给父元素添加storms(可以提高性能)
Ø原理:虽然风暴委托是基于风暴冒泡的特性
Ø实现:storm对象.target可以获取真正触发风暴的元素
<html lang="en">
<meta charset="UTF-8">
Title
我是第1个小li
我是第2个小li
我是第3个小li
我是第4个小li
我是第5个小li
//不要给每个li都添加事件了 而是把事件委托给他们的父亲元素
//事件委托是给父级提娜佳事件 而不是孩子添加事件
let ul = document.querySelector('ul');
ul.addEventListener('click',function (e) {
// alert('我被点击了');
e.target.style.color = 'red'; //e.target 获得父元素的被点击的那个对象
})
6.4 综合案例
渲染中学生信息案例
需求①:添加数据并点击输入按钮,将表单上的所有值放入链表并手动生成学号,即链表中最后一条数据的学号+1
需求②:渲染 将链表的数据渲染到页面,同时清除表单上的值,恢复下拉列表的值。 注意渲染之前,先清除原来渲染的内容。 由于需要多次渲染,最好封装成函数
需求③:删除数据,为了提高性能,最好采用风暴委托的形式。 根据当前删除链接查找并点击链接e.target.tagName,找到这条数据,需要使用findIndex方法找到链表元素所在的Thornton。 方便删除号码后,使用splice删除对应的数据,重新渲染
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
Document
<link rel="stylesheet" href="css/user.css">
新增学员
<div class="info">
姓名:<input type="text" class="uname">
年龄:<input type="text" class="age">
性别: <select name="gender" id="" class="gender">
<option value="男">男
<option value="女">女
薪资:<input type="text" class="salary">
就业城市:<select name="city" id="" class="city">
<option value="北京">北京
<option value="上海">上海
<option value="广州">广州
<option value="深圳">深圳
<option value="曹县">曹县
<button class="add">录入
就业榜
// 1. 准备好数据后端的数据
let arr = [
{ stuId: 1001, uname: '欧阳霸天', age: 19, gender: '男', salary: '20000', city: '上海' },
{ stuId: 1002, uname: '令狐霸天', age: 29, gender: '男', salary: '30000', city: '北京' },
{ stuId: 1003, uname: '诸葛霸天', age: 39, gender: '男', salary: '2000', city: '北京' },
];
//
//获取父元素
let tbody = document.querySelector('tbody');
//获得表单里面的值
let unmae = document.querySelector('.uname');
let age = document.querySelector('.age');
let gender = document.querySelector('.gender');
let salary = document.querySelector('.salary');
let city = document.querySelector('.city');
//渲染函数 把数组渲染到页面中
function render() {
//先干掉以前的数据,再渲染最新的数据
tbody.innerHTML= '';
//根据数据条数来渲染tr
for (let i = 0; i < arr.length; i++) {
//创建tr
let tr = document.createElement("tr");
//tr 里边放内容
tr.innerHTML = `
${arr[i].stuId} |
${arr[i].uname} |
${arr[i].age} |
${arr[i].gender} |
${arr[i].salary} |
${arr[i].city} |
<a href="javascript:" id="${i}">删除 |
`;
//给tr追加到tbody 父元素.appendChild(子元素);
tbody.appendChild(tr);
////复原所有的表单数据
unmae.value ='';
age.value ='';
gender.value = '男';
salary.value = '';
city.value = '北京';
}
}
render();
//获取录入按钮
let btn = document.querySelector('.add');
btn.addEventListener('click',function () {
//获得表单里面的值
let unmae = document.querySelector('.uname');
let age = document.querySelector('.age');
let gender = document.querySelector('.gender');
let salary = document.querySelector('.salary');
let city = document.querySelector('.city');
//加入数据
arr.push({
stuId: arr[arr.length -1].stuId + 1,
uname: unmae.value,
age: age.value,
gender: gender.value,
salary: salary.value ,
city: city.value
});
// console.log(arr);
render(); //渲染
})
//删除操作,删除也是数组里面的数据,用事件委托
tbody.addEventListener('click',function (e) {
//
// 我们只能点击了链接a,才会执行删除操作
//那么我怎么知道你点击了a呢
//俺们只能点击了链接才能做删除操作
//console.log(e.target.tagName);
if (e.target.tagName ==='A'){
// alert('A');
//删除操作,删除数组里面的数据 arr.splice()
//我要得到a的id
// console.log(e.target.id);
arr.splice(e.target.id,1);
render();
}
})
7.动画效果
<head lang="en">
<meta charset="UTF-8">
手风琴
ul {
list-style: none;
}
* {
margin: 0;
padding: 0;
}
div {
width: 1200px;
height: 400px;
margin: 50px auto;
border: 1px solid red;
overflow: hidden;
}
div li {
width: 240px;
height: 400px;
float: left;
transition: all 500ms;
}
div ul {
width: 1200px;
}
<div id="box">
<a href="#">
src="./images/1.jpg" alt="">
<a href="#">
src="./images/2.jpg" alt="">
<a href="#">
src="./images/3.jpg" alt="">
<a href="#">
src="./images/4.jpg" alt="">
<a href="#">
src="./images/5.jpg" alt="">
//1. li默认有个宽度是240px
//2. 当我们鼠标经过,当前的小li 宽度变大到800px,其余的变到100px //排他思想
//3. 鼠标离开的时候,就恢复为原来的效果
//获取元素
let lis = document.querySelectorAll('li');
//绑定鼠标经过和离开事件
for (let i = 0; i < lis.length; i++) {
//鼠标经过
lis[i].addEventListener('mouseenter',function () {
//排他思想 干掉所有人的100px,再复活自己的800px
for (let j = 0; j < lis.length; j++) {
lis[j].style.width = '100px';
}
this.style.width = '800px';
});
//鼠标离开
lis[i].addEventListener('mouseleave',function () {
//让所有的li变成240px
for (let j = 0; j < lis.length; j++) { // 事件触发执行,为了让所有li变成240宽的
lis[j].style.width = '240px';
}
})
}
7.1 滚滚风暴和装载风暴 7.1.1 滚滚风暴
页面滚动时触发风暴
为什么学习?
Ø很多网页需要检查用户将页面滚动到某个区域并做一些处理,比如修复导航栏,比如返回底部
风暴名称:卷轴
点击整个页面滚动:
window.addEventListener('scroll',function(){ //window是一个dom节点,换成其他节点也可以,div 等等
执行操作
})
给 window 或 document 添加 scroll 事件
监听元素内部滚动并直接添加到元素中
7.1.2 加载风暴
外部资源(如图片、外部CSS、JavaScript等)加载完成时触发
为什么学习?
Ø 有时你需要等待所有页面资源处理完毕才能做某事
Ø老代码喜欢把脚本写在头部。 这个时候是无法直接找到dom元素的
风暴名称:load
监听页面所有资源加载:
Ø 添加负载风暴到窗口
window.addEventListener('load',function(){ //window也可以换成其他dom节点
//执行操作
})
注意:不仅可以监听整个页面资源加载完成情况,还可以对某个资源绑定加载风暴
7.1.3 加载风暴2
DOMContentLoaded 事件在初始 HTML 文档完全加载和解析时触发,无需等待样式表、图像等完全加载
事件名称:DOMContentLoaded
监听页面DOM加载:
给 document 添加 DOMContentLoaded 事件
window.addEventListener('DOMContentLoaded',function(){
//执行操作
})
7.2 元件尺寸和位置 7.2.1 涡旋族
使用场景:我们希望将页面滚动一定的距离,比如100px,让单个元素显示和隐藏。 我们如何知道页面已经滚动了 100px? 您可以使用滚动来测量页面滚动的距离。
图像
获取宽度和高度:
•获取元素内容的总宽和高(不包括滚动条)返回值不带单位•scrollWidth和scrollHeight获取位置:•获取元素内容向左和向上滚动看不到的距离• scrollLeft和scrollTop•这两个属性是可以改变的
div.addEventListenner('scroll',function(){
console.log(this.scrollTop)
})
在开发中,我们经常会检查页面滚动距离,比如页面滚动100像素,就可以显示一个元素,或者可以固定一个元素
//页面滚动事件
window.addEventListener('scroll',function () {
let num = document.documentElement.scrollTop; //document.documentElement HTML文档返回对象为HTML元素
console.log(num);
})
案件:
页面滚动显示返回底部按钮
需求:当页面滚动500像素时,显示返回底部按钮,否则隐藏,同时点击按钮返回底部分析:
①:使用页面滚动风暴
②:检查页面滚动小于等于100像素,则显示按钮
③:点击按钮,将页面的scrollTop重置为0
<html lang="en">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Document
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.content {
width: 1000px;
height: 3000px;
background-color: pink;
margin: 0 auto;
}
.backtop {
display: none;
width: 50px;
left: 50%;
margin: 0 0 0 505px;
position: fixed;
bottom: 60px;
z-index: 100;
}
.backtop a {
height: 50px;
width: 50px;
background: url(./images/bg2.png) 0 -600px no-repeat;
opacity: 0.35;
overflow: hidden;
display: block;
text-indent: -999em;
cursor: pointer;
}
<div class="content">
<div class="backtop">
src="./images/close2.png" alt="">
<a href="javascript:;">
//获取对象
let backtop = document.querySelector('.backtop');
//页面滚动事件
window.addEventListener('scroll',function () {
let num = document.documentElement.scrollTop;
if (num >=500){
backtop.style.display = 'block';
}else {
backtop.style.display = 'none';
}
})
//点击链接返回顶部 backtop.children[1]
backtop.children[1].addEventListener('click',function () {
//返回顶部
//scrollTop可读写
document.documentElement.scrollTop = 0;
})
7.2.2 偏移系列
通过js的形式,我们可以获取到元素在页面中的位置,这样我们就可以进行操作了。 当页面滚动到这个位置时,可以返回到底部的小包里显示...
获取宽度和高度:
•获取元素自身的宽高,包括元素本身设置的宽高、padding、border•offsetWidth和offsetHeight
获取位置:
•获取该元素距您正在定位的父元素的左上距离 •ffsetLeft 和 offsetTop 是只读属性,不能作为形参
图像
7.2.1 仿易讯固定导航栏示例
需求:当页面滚动到秒杀模块时,导航栏手动滑入,否则滑出
分析:①:使用页面滚动风暴
②:检测页面滚动大于等于 秒杀模块的位置 则滑入,否则滑出
<html lang="en">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Document
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.content {
overflow: hidden;
width: 1000px;
height: 3000px;
background-color: pink;
margin: 0 auto;
}
.backtop {
display: none;
width: 50px;
left: 50%;
margin: 0 0 0 505px;
position: fixed;
bottom: 60px;
z-index: 100;
}
.backtop a {
height: 50px;
width: 50px;
background: url(./images/bg2.png) 0 -600px no-repeat;
opacity: 0.35;
overflow: hidden;
display: block;
text-indent: -999em;
cursor: pointer;
}
.header {
position: fixed;
top: -80px;
left: 0;
width: 100%;
height: 80px;
background-color: purple;
text-align: center;
color: #fff;
line-height: 80px;
font-size: 30px;
transition: all .3s;
}
.sk {
width: 300px;
height: 300px;
background-color: skyblue;
margin-top: 600px;
}
<div class="header">我是顶部导航栏
<div class="content">
<div class="sk">秒杀模块
<div class="backtop">
src="./images/close2.png" alt="">
<a href="javascript:;">
let sk = document.querySelector('.content .sk');
let header = document.querySelector('.header');
//console.log(sk.offsetTop)
window.addEventListener('scroll',function () {
let num = document.documentElement.scrollTop; //获得页面滑动的高度
if (num >= sk.offsetTop){
header.style.top = 0;
}else {
header.style.top = '-80px';
}
})
7.2.2 扶梯导航案例
需求:点击切换指定疗效
分析:
①:点击当前小导航,添加当前active,其余移除active
②:获取对应内容的offsetTop值
③:让页面的scrollTop到对应内容的offsetTop
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
Document
* {
margin: 0;
padding: 0;
}
.aside {
position: fixed;
left: 0;
top: 50%;
transform: translateY(-50%);
}
.item {
height: 40px;
line-height: 40px;
text-align: center;
padding: 0 10px;
cursor: pointer;
}
.active {
background-color: red;
color: #fff;
}
.content {
width: 660px;
margin: 400px auto;
}
.neirong {
height: 300px;
margin-bottom: 20px;
color: #fff;
}
.content1 {
background-color: red;
}
.content2 {
background-color: blue;
}
.content3 {
background-color: orange;
}
.content4 {
background-color: yellowgreen;
}
<div class="aside">
<div class="item active">男装/女装
<div class="item">儿童服装/游乐园
<div class="item">电子产品
<div class="item">电影/美食
<div class="content">
<div class="neirong content1">男装/女装
<div class="neirong content2">儿童服装/游乐园
<div class="neirong content3">电子产品
<div class="neirong content4">电影/美食
let aside = document.querySelectorAll('.item');
let goods = document.querySelectorAll('.neirong');
for (let i = 0; i <aside.length ; i++) {
//点谁到谁,谁高亮
aside[i].addEventListener('click',function () {
document.querySelector('.aside .active').classList.remove('active'); //找到上一个active类,移除
this.classList.add('active');
let num = goods[i].offsetTop;
document.documentElement.scrollTop = num; //让页面滚动到适当的位置
})
}
7.2.3 客户家庭
客户端当前可视区域
获取宽度和高度:
Ø获取元素可见部分的宽度和高度(不包括边框、滚动条等)
ØclientWidth 和 clientHeight
获取位置:
Ø 获取左边框和上边框的长度
ØclientLeft和clientTop是只读属性
窗口规格改变时会引发风暴:resize
window.addEventListener('resize',function(){
//执行的代码
})
检查屏幕长度
window.addEventListener('resize',function(){
let w = document.documentElement.clientWidth; //检测屏幕宽度
console.log(w);
})
您的三个种族的比较:
<html lang="en">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Document
* {
margin: 0;
padding: 0;
}
div {
width: 150px;
height: 150px;
background-color: pink;
overflow: auto;
padding: 10px;
border: 10px solid red;
margin: 100px;
}
我有很多很多的内容哦
我有很多很多的内容哦
我有很多很多的内容哦
我有很多很多的内容哦
我有很多很多的内容哦
我有很多很多的内容哦
我有很多很多的内容哦
我有很多很多的内容哦
我有很多很多的内容哦
我有很多很多的内容哦
我有很多很多的内容哦
我有很多很多的内容哦
我有很多很多的内容哦
我有很多很多的内容哦
// scrollWidth scrollHeight 内容 宽高 (了解)
let div = document.querySelector('div')
console.log(div.scrollWidth) // 150 不带单位
console.log(div.scrollHeight) // 336 不带单位
console.log('----------------------------')
// offset 盒子元素的大小 = 盒子本身的宽度和高度 + padding + border
console.log(div.offsetWidth) // 150 不带单位
console.log(div.offsetHeight) // 150 不带单位
// console.log(div.offsetTop) //
// console.log(div.offsetLeft)
// client 当前可视区域 不包含滚动条 边框等等
console.log('----------------------------')
console.log(div.clientWidth)
console.log(div.clientHeight)
console.log(div.clientTop) // 边框的宽度 了解 呵呵
console.log(div.clientLeft)
// 2. 被卷去的头部和左侧
// div.addEventListener('scroll', function () {
// console.log(document.querySelector('div').scrollTop)
// })
八、综合案例
轮播图案例分析:
需求①:小图标键盘经过暴风键盘经过小图,当前高亮高亮,其余兄弟淡入淡出添加一个类
要求②:大图跟随变化,对应大图跟随显示。 如果想要过渡效果可以使用不透明效果css点击后变色,可以使用CSS淡入淡出效果,或者添加一个类
需求③:点击左侧按钮,发挥疗效。 点击两侧按钮可手动播放下一张图片。 需要不断增加变量索引才能播放下一张图片。 如果到达最后一张图片,则必须恢复到第一张图片。
教你一招:搜索冒号=搜索冒号%链表宽度(放在播放的上面)
需求④:解决一个BUG,点击两侧的按钮可以播放下一首,但是当键盘经过后面时,会按照同样的顺序播放。
要求⑤:左键发挥疗效。 单击两侧按钮可手动播放上一张图片。 可变索引不断减小以播放上一张图片。 如果到达第一张图片,则必须从最后一张图片开始播放。
教你一招:搜索冒号=(链表宽度+搜索冒号)%链表宽度
需求⑥:由于两侧按钮和两侧按钮有很多相同的操作css点击后变色,因此可以提取一个公共的功能并进行封装
要求⑦:打开定时器。 虽然计时器是手动播放的,但是相当于点击两侧的按钮。 这时候,只需要,right.click()
要求⑧:键盘过去后,停止定时器(移除定时器),离开键盘启动定时器(启动定时器)
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
QQ音乐轮播图
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
li {
list-style: none;
}
.main {
width: 700px;
margin: auto;
background: #000;
}
.slides {
height: 320px;
position: relative;
}
.slides ul li {
/* display: none; */
position: absolute;
top: 0;
left: 0;
opacity: 0;
/* 这里实现淡入淡出的关键 */
transition: all .3s;
}
.slides li.active {
/* display: block; */
opacity: 1;
}
.slides .extra {
width: 700px;
height: 53px;
line-height: 53px;
position: absolute;
bottom: 0px;
background-color: rgba(0, 0, 0, 0.8);
z-index: 10;
}
.slides .extra h3 {
width: 82%;
margin: 0;
margin-right: 20px;
padding-left: 20px;
color: #98E404;
font-size: 28px;
float: left;
font-weight: 500;
font-family: "Microsoft Yahei", Tahoma, Geneva;
}
.slides .extra a {
width: 30px;
height: 29px;
display: block;
float: left;
margin-top: 12px;
margin-right: 3px;
background-image: url(./assets/icon_focus_switch.png);
}
.slides .extra .prev {
background-position: 0 0;
}
.slides .extra .prev:hover {
background-position: -30px 0;
}
.slides .extra .next {
background-position: -60px 0;
}
.slides .extra .next:hover {
background-position: -90px 0;
}
.indicator {
padding: 10px 0;
}
.indicator ul {
list-style-type: none;
margin: 0 0 0 4px;
padding: 0;
overflow: hidden;
}
.indicator ul li {
position: relative;
float: left;
width: 60px;
margin: 0 4px 0 5px;
text-align: center;
cursor: pointer;
}
.indicator li img {
display: block;
border: 0;
text-align: center;
width: 60px;
}
.indicator li .mask {
width: 60px;
height: 60px;
position: absolute;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.4);
}
.indicator li .border {
display: none;
width: 54px;
position: absolute;
bottom: 0;
left: 0;
z-index: 20;
border: 3px solid #98E404;
}
/* li里面的mask 和 border 刚开始都是显示的 */
/* 我们写一个样式css */
.indicator .active .mask {
display: none;
}
.indicator .active .border {
display: block;
}
<div class="main">
<div class="slides">
<li class="active"><a href="#"> src="./assets/b_01.jpg" alt="第1张图的描述信息">
<a href="#"> src="./assets/b_02.jpg" alt="第2张图的描述信息">
<a href="#"> src="./assets/b_03.jpg" alt="第3张图的描述信息">
<a href="#"> src="./assets/b_04.jpg" alt="第4张图的描述信息">
<a href="#"> src="./assets/b_05.jpg" alt="第5张图的描述信息">
<a href="#"> src="./assets/b_06.jpg" alt="第6张图的描述信息">
<a href="#"> src="./assets/b_07.jpg" alt="第7张图的描述信息">
<a href="#"> src="./assets/b_08.jpg" alt="第8张图的描述信息">
<a href="#"> src="./assets/b_09.jpg" alt="第9张图的描述信息">
<a href="#"> src="./assets/b_10.jpg" alt="第9张图的描述信息">
<div class="extra">
第1张图的描述信息
<a class="prev" href="javascript:;">
<a class="next" href="javascript:;">
<div class="indicator">
<li class="active">
src="assets/s_01.jpg">
<span class="mask">
<span class="border">
src="assets/s_02.jpg">
<span class="mask">
<span class="border">
src="assets/s_03.jpg">
<span class="mask">
<span class="border">
src="assets/s_04.jpg">
<span class="mask">
<span class="border">
src="assets/s_05.jpg">
<span class="mask">
<span class="border">
src="assets/s_06.jpg">
<span class="mask">
<span class="border">
src="assets/s_07.jpg">
<span class="mask">
<span class="border">
src="assets/s_08.jpg">
<span class="mask">
<span class="border">
src="assets/s_09.jpg">
<span class="mask">
<span class="border">
src="assets/s_10.jpg">
<span class="mask">
<span class="border">
//获取元素
let pics = document.querySelectorAll('.slides ul li');
let indicators = document.querySelectorAll('.indicator li');
let extra = document.querySelector('.extra h3');
let rightBtn = document.querySelector('.next');
let leftBtn = document.querySelector('.prev');
let main = document.querySelector('.main');
let index = 0; //全局变量 控制器 信号量
//需求①:小图标鼠标经过事件:鼠标经过小图片,当前高亮,其余兄弟变淡 添加类
//给多个li绑定事件
for (let i = 0; i < indicators.length; i++) {
indicators[i].addEventListener('mouseenter',function () {
document.querySelector('.indicator .active').classList.remove('active');
this.classList.add('active');
index = i; //需求④:解决一个BUG
//需求② :大图片跟随变化:对应的大图片跟着显示,
// 如果想要过渡效果,可以使用opacity效果,可以利用CSS淡入淡出的效果,还是添加类
document.querySelector('.slides ul .active').classList.remove('active');
pics[i].classList.add('active');
extra.innerHTML = `第${i+1}张图的描述信息`;
})
}
//需求③:右侧按钮播放效果,点击右侧按钮,可以自动播放下一张图片,
// 需要一个变化量 index 不断自增,然后播放下一张图片,如果到了最后一张,必须要还原为第1张图片
rightBtn.addEventListener('click',function () {
index++;
index = index % pics.length
common(index);
});
// 需求⑤:左侧按钮播放效果
leftBtn.addEventListener('click',function () {
index--;
index = (pics.length + index) % pics.length;
common(index);
});
// 需求⑥:
function common(index) {
// if (index === 10) index = 0;
//小图的操作:
document.querySelector('.indicator .active').classList.remove('active');
indicators[index].classList.add('active');
//大图的操作
document.querySelector('.slides ul .active').classList.remove('active');
pics[index].classList.add('active');
extra.innerHTML = `第${index+1}张图的描述信息`;
}
// 需求⑦:开启定时器
let timer = setInterval(function () {
//自动调用
rightBtn.click();
},1000)
// 需求⑧:鼠标经过停止定时器 (清除定时器)、鼠标离开开启定时器 (开启定时器)
main.addEventListener('mouseenter',function () {
clearInterval(timer)
});
main.addEventListener('mouseleave',function () {
timer = setInterval(function () {
//自动调用
rightBtn.click();
},1000)
});
悟空资源网 css css点击后变色-WEB API (JSDOM) https://www.wkzy.net/game/161820.html
-
如遇问题,请联系客服
客服QQ
QQ304192058