作用:通过使用js去操作html和浏览器
分类:
(Document Object Model)文档对象模型,是浏览器提供的一套专门用来操作网页内容的功能,即开发网页特效实现交互内容
将HTML文档以树状结构直观表现出来,称之为DOM树,是描述网页内容关系的名词。
作用是用树状图表示了标签与标签之间的关系
把网页内容当作对象处理,浏览器根据html标签生成js对象,所有标签属性都可以在这个对象上找到,修改这个对象的属性会自动映射到标签上。
所有对象的最上层,即DOM树的根上面还有一层,叫Document
document是DOM里提供的一个对象,网页所有内容都在document里面
<div>Hellodiv>
<script>
let d=document.querySelector('div')
console.dir(typeof d)
d.innerHTML='World'
d.style.color='red'
script>
即通过js选择标签再对其进行相关操作
document.querySelector('css选择器')
//参数可以包含一个或多个css选择器,返回匹配的第一个元素,一个HTMLElement对象,若没有匹配到返回null
<div>Hellodiv>
<div>Hello2div>
<script>
//获取元素,输入qs会自动生成
let d=document.querySelector('div')
console.log(d)
//输出结果:Hello
d.style.color='red'
script>
document.querySelectorAll('css选择器')
//参数可以包含一个或多个css选择器,返回多个元素,即NodeList对象集合
<div>Hellodiv>
<div>Hello2div>
<script>
//获取元素,输入qs会自动生成
let dlist = document.querySelectorAll('div')
console.log(dlist)
//输出结果:NodeList(2) [div, div]
for(let i=0;i<dlist.length;i++)
dlist[i].style.color='red'
script>
注:
querySelector
可以直接操作修改,但是querySelectorAll
获取的是一个数组,所以修改的时候需要进行遍历
document.getElementsByTagName
:获取页面上的某一种标签,获取的是一个选择集,不是数组,但是可以用下标的方式操作选择集里面的标签元素。
document.getElementById
:通过id获取标签,因为id只能使用一次,所以返回只有一个
document.getElementsByClassName
:通过类名获取标签选择集
document.getElementsByName
:通过name获取标签选择集
可以将文本追加到
前,并且文本中的标签也会被解析,这一块在Javascript基础已经学过。
将文本内容添加/更新到任意标签位置,但文本中的标签不会被解析
<div>Hellodiv>
<script>
//获取元素,输入qs会自动生成
let d=document.querySelector('div')
d.innerText='World'
script>
输出结果:将div标签中的文字更新为
<div>Worlddiv>
将文本内容添加/更新到任意标签位置,并且文本中的标签会被解析
<div>Hellodiv>
<script>
//获取元素,输入qs会自动生成
let d=document.querySelector('div')
d.innerHTML='World'
script>
输出结果:将div标签中的文字更新为
World
对象名.属性=值
<a href="https://www.baidu.com/">百度a>
<script>
//获取元素
let a=document.querySelector('a')
a.innerHTML='必应'
//修改元素属性
a.href="https://cn.bing.com"
script>
<div>Hellodiv>
<script>
let d=document.querySelector('div')
d.style.color='skyblue'
d.style.width='300px'
d.style.backgroundColor='white'
document.body.style.backgroundColor='skyblue'
//若设置body,则不需要获取,可以直接document.body
script>
如果属性有-连接符,如
background-color
则转化成小驼峰,即backgroundColor
赋值时css需要添加单位
若修改的样式比较多,直接通过style修改比较繁琐,则可以通过css类名的形势去修改
<head>
<style>
.box{
color:white;
width:300px;
height: 200px;
background-color:skyblue;
}
style>
head>
<body>
<div>Hellodiv>
<script>
let d=document.querySelector('div')
d.className='box'
//将d设置成box类的类型
script>
body>
由于class是关键字,所以需要className去代替
className是使用新的值去替换旧的值,若需要添加一个类,需要保留之前的类名,比如原来标签类名为
class="a"
,现在设置成class="b"
了;想要保存则可以设置成class="a b"
注:没有
idName
元素.classList.add('类名')
元素.classList.remove('类名')
元素.classList.toggle('类名')
<div class='box'>Hellodiv>
<script>
let d=document.querySelector('.box')
d.classList.add('a')
d.classList.add('b')
//结果:Hello
d.classList.remove('b')
//结果:Hello
d.classList.toggle('c')
//结果:Hello
d.classList.toggle('c')
//结果:Hello
script>
toggle切换指的是如果查询没有该类名则加上,若有则删除
表单很多情况也需要修改属性,比如输入密码时的小眼睛,点击可以看到密码,其本质就是将表单类型从密码转变为文本框
<input type="text" value="请输入">
<botton disabled>提交botton>
<input type="checkbox" class="check">
<script>
// 1.获取元素
let input=document.querySelector('input')
// 2.取值或设置值,得到input中的值可以使用value
input.type='password'
// 启用按钮
let btn=document.querySelector('botton')
btn.disable=false//若等于true表示不能使用,若false表示可以启用
//勾选复选框
let checkbox=document.querySelector('.check')
checkbox.checked=true
script>
定时器在javascript中的作用:
setTimeout(函数,间隔时间)
只执行一次的定时器
clearTimeout(变量名)
关闭只执行一次的定时器
setInterval(函数,间隔时间)
反复执行的定时器
clearInterval(变量名)
关闭反复执行的定时器
间隔时间是毫秒,1000毫秒=1秒
<div class="clock">div>
<script>
let clockbox = document.querySelector('.clock');
function timebox(){
//提取当前时间
let now = new Date();
let year = now.getFullYear();
let month = now.getMonth()+1;//month是从0-11
let date = now.getDate();
let week = now.getDay();//星期是从0-6
let hour = now.getHours();
let minute = now.getMinutes();
let second = now.getSeconds();
let str = '当前时间是:'+ year + '年'+month+'月'+date+'日 '+toweek(week)+' '+hour+':'+minute+':'+second;
clockbox.innerHTML = str;
}
//提取星期,因为now.getDay();返回的是0-6
function toweek(n){
if(n==0) return '星期日'
else if(n==1) return '星期一'
else if(n==2) return '星期二'
else if(n==3) return '星期三'
else if(n==4) return '星期四'
else if(n==5) return '星期五'
else return '星期六'
}
timebox();
let clock=setInterval(timebox,1000);
clearInterval(clock);
script>
<textarea style="width: 260px;">
用户协议
请您阅读完后点击确认
textarea>
<br>
<button class="btn" disabled>确认(6)button>
<script>
//1.获取元素
let btn=document.querySelector('.btn')
//2.计算逻辑
let count=6 //计数
let time=setInterval(function(){
count--
btn.innerHTML=`确认(${count})`
if(count==0)
{
//关闭定时器
clearInterval(time)
//开启按钮
btn.disabled=false
//更换文字
btn.innerHTML=`确认`
}
},1000)
script>
事件是在编程时系统内发生的动作或者发生的事情
让程序检测是否有事件,若有事件触发则立即调用一个函数做出响应,也称为注册事件
元素.addEventListener('事件',要执行的函数)
事件源:DOM元素被事件触发,需要获取DOM元素
事件:用什么方式触发
注:事件是字符串
事件类型:
- 鼠标触发:
- click鼠标点击
- mousemove鼠标移动
- mouseover 鼠标进入(进入子元素也触发)
- mouseout 鼠标离开(离开子元素也触发)
- mouseenter 鼠标进入(进入子元素不触发)尽量使用这个
- mouseleave 鼠标离开(离开子元素不触发)尽量使用这个
- hover同时为mouseenter和mouseleave事件指定处理函数
- scroll 滚动条的位置发生变化
- 焦点事件:表单获得光标
- focus获得焦点
- blur失去焦点
- submit用户递交表单
- 键盘事件:键盘触发
- keydown键盘按下触发
- keyup键盘抬起触发
- 文本事件:表单输入触发
- input用户输入事件
- ready() DOM加载完成
- resize() 浏览器窗口的大小发生改变
事件调用的函数:要做的事情
<div class="imgbox">
<img src="image/background.jpg">
<div class="chahao" style="color: black;">xdiv>
div>
<script>
let imgbox=document.querySelector('.imgbox')
let chahao=document.querySelector('.chahao')
chahao.addEventListener('click',function(){
//隐藏盒子
imgbox.style.display='none'
})
script>
开始下拉菜单隐藏
表单获得焦点就显示下拉菜单并将文本框变色
表单失去焦点,反向操作
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul{
list-style: none;
}
.mi{
position: relative;
width: 200px;
margin: 100px auto;
}
.mi input{
width: 200px;
height: 50px;
padding: 0 10px;
font-size: 14px;
line-height: 50px;
border: 1px solid #e0e0e0;
outline: none;
}
.mi .search{
border: 10px solid #ff6700;
}
.resultList{
display: none;
position: absolute;
left: 0;
top: 50px;
width: 200px;
border: 1px solid #ff6700;
border-top: 0;
background: #fff;
}
.resultList a{
display: block;
padding: 6px 15px;
font-size: 12px;
color: #424242;
text-decoration: none;
}
.resultList a:hover{
background-color: #eee;
}
style>
<div class="mi">
<input type="search" placeholder="请输入产品名">
<ul class="resultList">
<li><a href="#">全部商品a>li>
<li><a href="#">小米笔记本a>li>
<li><a href="#">小米手环a>li>
<li><a href="#">小米手机a>li>
ul>
div>
<script>
//1.获取元素
//使用属性选择器选择search
let search=document.querySelector('input[type=search]')
let resultList=document.querySelector('.resultList')
//2.事件函数
search.addEventListener('focus',function(){
resultList.style.display='block';
})
search.addEventListener('blur',function(){
resultList.style.display='none';
})
script>
<div class="Weibo">
有什么新鲜事想要告诉大家?<br>
<textarea placeholder="说点什么吧..." id="area" cols="30" rows="10" maxlength="200">textarea>
<div class="foot">
<span>0span>/200
<button>发布button>
div>
div>
<script>
let area=document.querySelector('#area')
let text=document.querySelector('.foot span')
let fontNum=0
area.addEventListener('input',function(){
fontNum=area.value.length
text.innerHTML=fontNum
if(fontNum!=0&&fontNum<200)
text.style.color='black'
else
text.style.color='red'
})
script>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.FuXuan{
width: 500px;
border: 1px solid skyblue;
text-align: center;
border-collapse: collapse;
margin: 0 auto;
}
.FuXuan th{
background-color: skyblue;
color: white;
}
.FuXuan td{
border: 1px solid skyblue;
}
style>
<div>
<table class="FuXuan">
<tr>
<th><input type="checkbox" class="checkAll"><span class="QuanXuan">全选span>th>
<th>商品th>
<th>商家th>
<th>价格th>
tr>
<tr>
<td><input type="checkbox" class="check1">td>
<td>红米K40td>
<td>小米td>
<td>¥1999td>
tr>
<tr>
<td><input type="checkbox" class="check2">td>
<td>OPPO Findx3td>
<td>OPPOtd>
<td>¥3000td>
tr>
<tr>
<td><input type="checkbox" class="check3">td>
<td>Iphone13td>
<td>苹果td>
<td>¥6000td>
tr>
table>
div>
<script>
let QuanXuan=document.querySelector('.QuanXuan')
let checkAll=document.querySelector('.checkAll')
let check=document.querySelectorAll('.check')
checkAll.addEventListener('click',checkAllNum)
for(let i=0;i<check.length;i++)
check[i].addEventListener('click',checkNum)
function checkNum(){
for(let i=0;i<check.length;i++)
{
if(check[i].checked==false)
{//若有未选的直接退出
QuanXuan.innerHTML='全选'
checkAll.checked=false
return
}
}
QuanXuan.innerHTML='取消'
checkAll.checked=true
}
function checkAllNum(){
if(checkAll.checked==true)
{
QuanXuan.innerHTML='取消'
for(let i=0;i<check.length;i++)
check[i].checked=true
}
else
{
QuanXuan.innerHTML='全选'
for(let i=0;i<check.length;i++)
check[i].checked=false
}
}
script>
可以理解为函数的高级使用,把函数当作值来对待的函数就是高级函数
let 变量名=function(){}
如果将一个函数当作一个参数传递给另一个参数,那么当参数的函数称为回调函数。比较常见的是使用匿名函数当作回调函数
比如:checkAll.addEventListener('click',checkAllNum)
中的checkAllNum
就是回调函数
环境对象指的是函数内部特殊的变量this
,代表当前函数运行时所处的环境。目的是让代码更加简洁。
this就是一个对象,普通函数this指向window,因为直接调用函数,相当于是
window.函数
,所以this指向window
function fn(){console.log(this)}
//结果:Window
btn.addEventListener('click',function(){console.log(this)})
//结果:
粗略的规则:谁调用,this就指向谁
//原来
btn.addEventListener('click',function(){
btn.style.color='red'
})
//使用this
btn.addEventListener('click',function(){
this.style.color='red'
})
就是比如标签,只有选择的那一项会改变模样,其他不变,实现方法就是先将所有元素的样式关闭,然后只打开自己
for(let i=0;i<btns.length;i++)
btns[i].addEventListener('chick',function(){
// //干掉所有人
// for(let j=0;j
// btns[j].classList.remove('pink')
//改进:因为只有一个会是pink样式,找到那唯一的一个pink类,然后删除
document.querySelector('.pink').classList.remove('pink')
//只打开自己
this.classList.add('pink')
}
})
DOM树中的每个内容都称之为节点
<div class="a">
<div class="b">
<img src="" class="image">
<div class="c">div>
div>
div>
节点.parentNode
:返回最近一级的父结点,找不到则返回null,若想找再上一层可以继续.parentNodelet image=document.querySelector('.image')
//查找父节点,得到...
console.log(image.parentNode)
//查找父节点的父节点,得到...
console.log(image.parentNode.parentNode)
节点.childNodes
:获得所有子节点,包括文本节点(空格、换行)、注释节点等节点.children
(重点):仅获得所有元素节点,返回的还是一个数组let father=document.querySelector('.b')
//查找孩子节点,结果为:NodeList(5) [text, img.image, text, div.c, text]
console.log(father.childNodes)
//查找孩子节点,结果为:HTMLCollection(2) [img.image, div.c]
console.log(father.children)
节点.nextElementSibling
:查找下一个兄弟节点节点.previousElementSibling
:查找上一个兄弟节点//查找下一个兄弟节点,结果为:
let next=image.nextElementSibling
console.log(next)
//查找上一个兄弟节点,结果为:
console.log(next.previousElementSibling)
创建新的节点并放到指定位置
document.createElement('新的标签')
//创建标签
let d=document.createElement('div')
//添加class
div.className='d'
元素.appendChild(要插入的元素)
//追加到父元素最后一个子元素后面
let b=document.querySelector('.b')
b.appendChild(d)
//添加内容
d.innerHTML='class=d'
元素.insertBefore(要插入的元素,在哪个元素前)
//追加到父元素第一个子元素前面
b.insertBefore(d,b.children[0])
在页面排列图片或者其他元素时,之前学的是用document.write(),这个方法并不好,因为需要在script内渲染,学到这里,我们就可以使用节点进行追加
<div>
<table>
<caption>学生列表caption>
<tr>
<th>序号th>
<th>姓名th>
<th>年龄th>
<th>性别th>
tr>
table>
div>
<script>
let student=[
{name:'张三',age:20,gender:'男'},
{name:'李四',age:21,gender:'女'},
{name:'王五',age:19,gender:'男'},
{name:'钱六',age:22,gender:'男'}
]
let table=document.querySelector('table')
for(let i=0;i<student.length;i++)
{
//追加行节点
let tr=document.createElement('tr')
table.appendChild(tr)
//追加序号
let No=document.createElement('td')
tr.appendChild(No)
No.innerHTML=`${i+1}`
//循环追加学生信息
for(let k in student[i])
{
let st=document.createElement('td')
tr.appendChild(st)
st.innerHTML=`${student[i][k]}`
}
}
script>
元素.cloneNode(布尔值)
无缝滚动使用的就是克隆节点,就是复制一个原有的节点,再将复制的节点放到指定位置。
若为true则克隆会包含后代节点一起克隆
若为false则不克隆后代
<div class="a">
<div class="b">
<img src="" class="image">
<div class="c">div>
div>
div>
<script>
let b=document.querySelector('.b')
//克隆b
let newb=b.cloneNode(true)
//放到c的子节点
let c=document.querySelector('.c')
c.appendChild(newb)
//放到最外层body内
document.body.appendChild(newb)
script>
父元素.removeChild(要删除的孩子元素)
//删除刚才克隆到c内的b
c.removeChild(b)
在代码中如果发现new关键字,一般将这个操作称为实例化
let date=new Date()
//获得当前时间
let date=new Date()
//获得指定时间,比如做倒计时的时候
let date2=new Date(2022,01,01,01,00,00)
let date2=new Date('2022-01-01 01:00:00')
时间对象返回的数据不能直接使用,需要使用一些方法进行转换格式
方法 | 作用 | 范围 |
---|---|---|
getFullYear() | 年 | |
getMonth() | 月 | 0~11 |
getDate() | 日 | |
getDay() | 星期 | 0~6 |
getHours() | 时 | 0~23 |
getMinutes() | 分 | 0~59 |
getSeconds() | 秒 | 0~59 |
注:
月份是从0开始,所以需要加1;
星期是数字从0-6,所以需要转换成星期日、星期一、星期二、…、星期六
时间戳是指从1970年1月1日0时0分0秒到现在的毫秒数,是用来计算时间的,是一种特殊的计量时间的方式。最常见的应用是倒计时,即将结束的时间的时间戳减去开始的时间的时间戳,得出剩余的时间毫秒数。
获得时间戳方式:(三种)
时间.getTime()
:可以得到当前也可以得到指定时间的时间戳+new Date()
:可以得到当前也可以得到指定时间的时间戳Date.now()
:但只能得到当前时间戳let date=new Date()
let date2=new Date('2022-01-01 01:00:00')
//获得当前时间的时间戳
console.log(date.getTime())
console.log(+new Date())
console.log(Date.now())
//获得指定时间的时间戳
console.log(date2.getTime())
console.log(+new Date('2022-01-01 01:00:00'))
倒计时转换公式:
总秒数=parseInt((future-now)/1000)
天数=parseInt(总秒数/60/60/24)
小时数=parseInt(总秒数/60/60%24)
分钟数=parseInt(总秒数/60%60)
秒数=parseInt(总秒数%60)
倒计时的时间差也可以直接使用时间对象相减
//倒计时:future是未来的时间,now是现在的时间
let now=new Date()
let future=new Date('2022-05-24 09:10:00')
//得出时间差,转换成秒数
let count = parseInt((future-now)/1000);
//得出天数,86400=60*60*24
let day = parseInt(count/60/60/24);
//得出小时
let hour = parseInt(count/60/60%24);
//得出分钟
let min = parseInt(count/60%60);
//得出秒
let sec = parseInt(count%60);
console.log(count,day,hour,min,sec);
当Render Tree中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或者全部文档的过程称为回流。
如:页面首次刷新;浏览器窗口大小发生改变;元素大小或位置发生改变;激活css伪类;DOM操作(如添加、删除DOM元素)
因为节点的样式发生改变,但是并不影响布局时,称为重绘
如:设置背景色、设置字体颜色等等
重绘不一定会引起回流,但是回流一定会引起重绘
事件对象也是一个对象,存放事件触发时的相关信息。在事件绑定的回调函数的第一个参数就是事件对象,并且一般命名为event、ev、e
,如鼠标点击事件中:元素.addEventListener('click',function(e){})
,事件对象e
就存放了鼠标点击的位置等信息。可以使用console.log(e)
查看事件对象详情
type
:获取当前事件的类型
clientX/clientY
:获取光标相对于浏览器可见窗口左上角的位置
offsetX/offsetY
:获取光标相对于当前DOM元素左上角的位置
key
:用户按下的键盘键的值
注:现在不提倡使用keyCode
<img src="./image/logo.jpg" class="logo" style="left: 0;top:0;position:absolute;width: 60px;height: 50px;">
<script>
let logo=document.querySelector('.logo')
let move=addEventListener('mousemove',function(e){
//因为在图片左上角,所以想要在图片中间可以修改一下,减图片的一半
logo.style.left=e.clientX-30+'px'
logo.style.top=e.clientY-25+'px'
})
setInterval(move,1000)
script>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>微博输入改进title>
<style>
*{
margin: 0;
padding: 0;
}
textarea{
width: 500px;
border: 1px solid skyblue;
font-size: 20px;
color:black;
}
.Weibo{
width: 500px;
margin: 0 auto;
color: skyblue;
}
.foot{
color: black;
float: right;
}
.foot span{
color: red;
}
.text{
padding-top: 100px;
width: 500px;
margin: 0 auto;
}
ul{
display: block;
width: 500px;
}
li{
list-style: none;
display: block;
word-wrap: break-word;
width: 480px;
padding: 10px 10px;
margin: 10px 0;
border: 1px solid skyblue;
border-radius:10px;
}
.time{
text-align: right;
color: skyblue;
}
style>
head>
<body>
<div class="Weibo">
有什么新鲜事想要告诉大家?<br>
<textarea placeholder="说点什么吧..." id="area" cols="30" rows="10" maxlength="200">textarea>
<div class="foot">
<span>0span>/200
<button>发布button>
div>
div>
<div class="text">
<ul>
ul>
div>
<script>
let area=document.querySelector('#area')
let text=document.querySelector('.foot span')
let fontNum=0
area.addEventListener('input',function(){
fontNum=area.value.length
text.innerHTML=fontNum
if(fontNum!=0&&fontNum<200)
text.style.color='black'
else
text.style.color='red'
})
//按下回车生成留言信息
let btn=document.querySelector('button')
let ul=document.querySelector('ul')
function btn_display(){
if(area.value.trim()==''){
area.value=''
text.innerHTML=0
alert('内容不能为空')
return
}
else{
let li=document.createElement('li')
ul.insertBefore(li,ul.children[0])
li.innerHTML=area.value
area.value=null
let date=new Date()
let time=document.createElement('div')
li.appendChild(time)
time.className='time'
let year=date.getFullYear()
let month=date.getMonth()
let day=date.getDay()
let hour=date.getHours()
let min=date.getMinutes()
time.innerHTML=year+'年'+month+'月'+day+'日'+hour+':'+min
text.innerHTML=0
text.style.color='red'
}
}
btn.addEventListener('click',btn_display)
area.addEventListener('keyup',function(e){
//按下回车键
console.log(e.key);
if(e.key=='Enter'){
btn_display()
}
})
script>
body>
html>
指事件完整执行过程中的流动路径,先捕获,然后冒泡
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称之为事件冒泡。
即:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件
<style>
.father{
margin: 100px auto;
width: 500px;
height: 500px;
background-color: skyblue;
}
.son{
width: 200px;
height: 200px;
background-color: black;
}
style>
<div class="father">
<div class="son">div>
div>
<script>
let f=document.querySelector('.father')
let s=document.querySelector('.son')
f.addEventListener('click',function(){
alert('father')
})
s.addEventListener('click',function(){
alert('son')
})
script>
此时点击father框会弹出father,但是点击son不仅会弹出son,还会弹出father,即会将其父级元素的相同事件一起触发。若father上级还有相同的事件也会触发,若不同事件则不会被触发。
事件冒泡是默认存在的
DOM.addEventlistener(事件类型,事件处理函数,是否使用捕获机制)
从DOM的根元素开始去执行对应的事件(从外到内),并且事件捕获需要编写对应代码才能看到效果
<style>
.father{
margin: 100px auto;
width: 500px;
height: 500px;
background-color: skyblue;
}
.son{
width: 200px;
height: 200px;
background-color: black;
}
style>
<div class="father">
<div class="son">div>
div>
<script>
let f=document.querySelector('.father')
let s=document.querySelector('.son')
f.addEventListener('click',function(){
alert('father')
},true)
s.addEventListener('click',function(){
alert('son')
},true)
document.addEventListener('click',function(){
alert('body')
},true)
script>
此时点击son会首先弹出body,然后弹出father,最后弹出son;若点击father则首先弹出body,然后弹出father;若点击body只会弹出body。即若开启捕获,则会从根元素开始去执行对应的事件。和冒泡正好相反。
捕获本身不重要,开发中基本不用,只用理解即可,主要是使用事件冒泡
因为默认冒泡,那么容易导致事件影响到父级元素,若想让事件不影响父级元素,则需要阻止事件流动。阻止事件流动:在事件中:e.stopPropagation()
let f=document.querySelector('.father')
let s=document.querySelector('.son')
f.addEventListener('click',function(e){
alert('father')
//阻止流动 Propagation:传播
e.stopPropagation()
})
s.addEventListener('click',function(e){
alert('son')
//阻止流动
e.stopPropagation()
})
此方法不仅可以阻断冒泡,还可以阻断捕获
之前学到的事件中
mouseover
鼠标进入(有冒泡)mouseout
鼠标离开(有冒泡)mouseenter
鼠标进入(没有冒泡)mouseleave
鼠标离开(没有冒泡)所以尽量使用mouseenter
鼠标进入和mouseleave
鼠标离开
e.preventDeafult()
比如链接点击不跳转,表单域不提交
<a href="http://www.baidu.com">baidua>
<script>
let a=document.querySelector('a')
a.addEventListener('click',function(e){
//点击链接不跳转,阻止默认行为
e.preventDefault()
})
script>
传统on注册(L0)—不常用了
同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
<button>点击button>
<script>
let btn=document.querySelector('button')
btn.onclick=function(){
alert('onclick1')
}
btn.onclick=function(){
alert('onclick2')
}
script>
执行结果:
执行的话只会显示onclick2,会覆盖前面的事件
直接使用null覆盖偶就可以实现事件的解绑
btn.onclick=null
执行结果:
之前注册的事件将不会执行,也就是解绑
都是冒泡阶段执行的
事件监听注册(L2)
语法: addEventListener(事件类型,事件处理函数,是否使用捕获)
后面注册的事件不会覆盖前面注册的事件(同一个事件)
<button>点击button>
<script>
let btn=document.querySelector('button')
btn.addEventListener('click',function(){
alert('click1')
})
btn.addEventListener('click',function(){
alert('click2')
})
script>
执行结果:
执行的话会依次显示click1、click2
解绑:
removeEventListener(事件类型,事件处理函数,获取捕获或者冒泡阶段)
btn.addEventListener('click',Falert)
function Falert(){
alert('click1')
}
btn.removeEventListener('click',Falert)
//但是若是在注册事件参数中写的匿名函数function(){}则不能解绑
可以通过第三个参数去确定是在冒泡或者捕获阶段执行
事件委托是利用事件流的特征解决一些开发需求的知识技巧。
事件委托是利用事件冒泡的特点,给父节点添加事件,当点击子节点时会向上冒泡,冒泡到其父节点触发事件。即把子结点的事件委托给父节点,从而简化操作和提高性能。
注:
事件对象.target
可以获得真正触发事件的元素,即子节点,是整个元素事件对象.target.tagName
找到获得真正触发事件的元素标签名事件对象.target.id
获取数据的索引号
<ul>
<li>1li>
<li>2li>
<li>3li>
<li>4li>
<li>5li>
ul>
<script>
//不要每个li都注册事件,而是把事件委托给其父节点ul
let ul=document.querySelector('ul')
ul.addEventListener('click',function(e){
//即通过冒泡性,点击其子结点时会向上冒泡,发现其父节点有点击事件,则会执行
// alert('点击li')
//得到点击的当前元素,即会得到li
// console.log(e.target)
//设置点击哪个li哪个li就变红
e.target.style.color='red'
})
script>
点击录入按钮,可以添加学生信息,主要目的是为了后面学习Vue做铺垫(数据驱动视图),即主要是操作数组数据,从而重新渲染页面
需求1:添加数据
需求2:渲染
把数组的数据渲染到页面中,同时清空表单内的值,下拉列表的值复原
注意:渲染之前,先清空以前渲染的内容
因为多次渲染,最好封装为函数
需求3:删除
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>Documenttitle>
<style>
*{
margin: 0;
padding: 0;
}
input{
width: 70px;
border: 1px solid skyblue;
}
select{
border: 1px solid skyblue;
}
button{
width: 40px;
color: white;
background-color:teal;
border-radius: 5px;
}
h2{
margin-top: 20px;
text-align: center;
}
table{
text-align: center;
width: 700px;
border: 1px solid skyblue;
border-collapse: collapse;
}
tr,th,td{
height: 50px;
border: 1px solid teal;
}
th{
background-color: skyblue;
}
tbody tr:hover{
background-color: #eee;
}
a {
text-decoration: none;
color: teal;
}
.add{
width: 700px;
margin: 0 auto;
}
style>
head>
<body>
<div class="add">
<h2>新增学生h2><br>
姓名:<input type="text" class="name">
年龄:<input type="text" class="age">
性别:<select name="gender" class="gender">
<option value="男">男option>
<option value="女">女option>
select>
薪资:<input type="text" class="salary">
就业城市:<input type="text" class="city">
<button class="add_btn">录入button>
<h2>学生信息表h2>
<table>
<thead>
<tr>
<th>学号th>
<th>姓名th>
<th>年龄th>
<th>性别th>
<th>薪资th>
<th>就业城市th>
<th>删除th>
tr>
thead>
<tbody>
tbody>
table>
div>
<ul>
ul>
<script>
let student=[
{id:1001,name:'张三',age:20,gender:'男',salary:'15',city:'北京'}
]
let tbody=document.querySelector('tbody')
//根据数组进行渲染
function showTable(){
//先删除以前的数据
tbody.innerHTML=''
//再渲染新的数据
for(let i=0;i<student.length;i++)
{
//创建tr
let tr=document.createElement('tr')
//tr内的内容
tr.innerHTML=`
${student[i].id}
${student[i].name}
${student[i].age}
${student[i].gender}
${student[i].salary}
${student[i].city}
${i}">删除
`
//给删除添加id以方便删除时获取id
tbody.appendChild(tr)
}
}
showTable()
//添加学生
//获取提交按钮
let add_btn=document.querySelector('.add_btn')
//获取各个表单元素
let name=document.querySelector('.name')
let age=document.querySelector('.age')
let gender=document.querySelector('.gender')
let salary=document.querySelector('.salary')
let city=document.querySelector('.city')
//添加点击提交事件
add_btn.addEventListener('click',function(){
//若非空则添加到数组
if(Empty(name.value)&&Empty(age.value)&&Empty(gender.value)&&Empty(salary.value)&&Empty(city.value)){
let stuId
if(student.length!=0)
stuId=student[student.length-1].id+1
else//若数组为空,则学生学号从1001开始
stuId=1001
student.push({
id: stuId,//最后一个元素的Id+1
name: name.value,
age: age.value,
gender: gender.value,
salary: salary.value,
city: city.value
})
//重新渲染函数
showTable()
//将表单恢复为空
name.value=age.value=salary.value=city.value=''
gender.value='男'
}
}
)
//判断input非空,之后可以使用正则
function Empty(value){
if(value.trim()!='') return true
else{
alert('添加学员数据不可为空')
return false
}
}
//事件委托进行删除
let del=document.querySelector('tbody')
del.addEventListener('click',function(e){
// console.log(e.target.tagName)
// 点击的标签名,当为A时执行
if(e.target.tagName=='A'){
//获取id,比如点击第一个,则返回0,即a中id保存的是其在数组中的位置
//console.log(e.target.id);
student.splice(e.target.id,1)
//重新渲染页面
showTable()
}
})
script>
body>
html>
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>Documenttitle>
<style>
*{
margin: 0;
padding: 0;
}
div{
width: 1000px;
margin: 0 auto;
font-size:0;
/* 消除img之间的空隙 */
}
img{
width: 200px;
height:500px
}
.show{
width: 800px;
}
.hidden{
width: 50px;
}
style>
head>
<body>
<div>
<img src="image/1.jpg">
<img src="image/2.jpg">
<img src="image/3.jpg">
<img src="image/4.jpg">
<img src="image/5.jpg">
div>
<script>
let imglist=document.querySelectorAll('img')
// imglist[0].classList.add('show')
for(let i=0;i<imglist.length;i++)
{
//鼠标经过
imglist[i].addEventListener('mouseenter',function(){
for(let j=0;j<imglist.length;j++)
//目前多个元素一起设置只能一个一个设置,到后期学其他的可以一下子一起设置
imglist[j].classList.add('hidden')
this.classList.remove('hidden')
this.classList.add('show')
})
//鼠标离开
imglist[i].addEventListener('mouseleave',function(){
for(let j=0;j<imglist.length;j++){
imglist[j].classList.remove('show')
imglist[j].classList.remove('hidden')
}
})
}
script>
body>
html>
scroll
当页面进行滚动时触发,比如滚动时固定导航栏、或者点击按钮可以直接返回顶部
用到最多的就是监听整个页面滚动—window.addEventListener('scroll',function(){})
load
、DOMContentLoaded
加载外部资源(如图片、外联CSS和Javascript等)加载完毕时触发事件。
有些时候需要等页面资源全部处理完了做一些事情;
或者老代码喜欢把script写到head中,这时候直接找DOM元素找不到
用到最多的就是监听所有资源加载完毕—window.addEventListener('load',function(){})
这个事件可以放到任何地方,因为是要等所有资源加载完毕才执行,但是还是提倡写在下面
当初始HTML文档被完全加载和解析完成触,而无需等待样式表、图像等完全加载
掌握元素大小和位置的获取方式,为后续网页特效打基础
scroll家族★
offset家族★
client家族
比如我们想要页面滚动一段距离后就将一些元素显示或隐藏,那么就可以使用scroll来检测滚动距离
scrollWidth
和scrollHeight
:元素内容的总宽高,不包含滚动条获取元素的内容总宽高(不包含滚动条)返回值不带单位
<style>
div{
width: 100px;
height: 100px;
background-color: skyblue;
/* 滚动条 */
overflow: auto;
}
style>
<div>
大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好
div>
<script>
let div=document.querySelector('div')
//内容的大小
console.log(div.scrollWidth)//100不带单位
console.log(div.scrollHeight)//478不带单位
//有了滚动条后内容的宽度改变为83,高度为582
script>
scrollLeft
和scrollTop
获取元素内容向左或者向上滚动出去看不到的距离,这两个属性是可以修改的
//页面滚动事件
window.addEventListener('scroll',function(){
//获取当前页面被卷去的头部
let num=document.documentElement.scrollTop
//可以修改,即只要一滚动那么会直接滚动到500
documentElement.scrollTop=500
console.log(num)
})
window.addEventListener('scroll',function(){
//获取当前页面被卷去的左边
let num=document.documentElement.scrollLeft
console.log(num)
})
document.documentElement
是整个页面文档即...
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>Documenttitle>
<style>
a{
text-decoration: none;
color:black;
font-size: 35px;
}
.return{
background-color: aquamarine;
border-radius: 50px;
width: 50px;
height: 50px;
position: fixed;
right:10px;
bottom: 10px;
text-align: center;
}
.text{
width: 100px;
height:2000px;
background-color:skyblue;
}
style>
head>
<body>
<div class="text">div>
<div class="return"><a href="javascript:">⬆a>div>
<script>
let ret=document.querySelector('.return')
//页面滚动事件
window.addEventListener('scroll',function(){
let num=document.documentElement.scrollTop
console.log(num)
//当顶部向上滚动到500时显示返回顶部按钮
if(num>=500)
ret.style.display='block'
else
ret.style.display='none'
})
//点击返回事件
ret.addEventListener('click',function(){
document.documentElement.scrollTop=0
})
script>
body>
html>
前面案例滚动多少距离,都是我们自己算的(如上面例子中的500),最好是页面滚动到某个元素,就可以做某些事。
简单说,就是通过js的方式,得到元素在页面中的位置这样我们可以做,页面滚动到这个位置,就可以返回顶部的小盒子显示。如当我们滑动到某个元素距离顶部多少像素时,显示返回顶部
offsetWidth
和offsetHeight
:元素自身宽高,包含padding和border获取元素的自身宽高、包含元素自身设置的宽高、padding、border
let div=document.querySelector('div')
//盒子的大小,和内容无关,包含padding、border
console.log(div.offsetWidth)//100不带单位
console.log(div.offsetHeight)//100不带单位
offsetLeft
和offsetTop
获取元素距离自己定位父级元素的左、上距离,若父级没有定位则一层一侧向上找,直到body。这两个属性是只读属性,不可以修改
let div=document.querySelector('div')
//页面滚动事件
window.addEventListener('scroll',function(){
console.log(div.offsetTop)
console.log(div.offsetLeft)
})
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
header{
position: fixed;
top: -80px;
/* 当滚动到一定位置再改为0 */
left: 0;
width: 100%;
height: 80px;
background-color: purple;
text-align: center;
color: white;
transition: all .3s;
}
.content{
overflow: hidden;
width: 1000px;
height: 3000px;
background-color: pink;
margin: 0 auto;
}
.sk{
width: 300px;
height: 300px;
background-color: skyblue;
margin-top: 500px;
}
style>
<header>导航栏header>
<div class="content">
<div class="sk">秒杀模块div>
div>
<script>
let header=document.querySelector('header')
let sk=document.querySelector('.sk')
//1.页面滚动事件
window.addEventListener('scroll',function(){
//2.检测滚动的距离>=秒杀模块的offsetTop,则滑入
if(document.documentElement.scrollTop>=sk.offsetTop)
header.style.top=0
else
header.style.top='-80px'
})
script>
需求:
①点击当前小导航栏,当前添加active,其余移除active
②得到对应内容的offsetTop值
③让页面的scrollTop走到对应内容的offsetTop
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
height: 3000px;
}
.content1{
width: 600px;
height: 400px;
background-color: blueviolet;
margin: 10px auto;
color: white;
}
.content2{
width: 600px;
height: 400px;
background-color: blue;
margin: 10px auto;
color: white;
}
.content3{
width: 600px;
height: 400px;
background-color: cadetblue;
margin: 10px auto;
color: white;
}
.content4{
width: 600px;
height: 400px;
background-color: burlywood;
margin: 10px auto;
color: white;
}
.item{
text-decoration: none;
color: #000;
display: block;
width: 60px;
text-align: center;
}
.active{
color: white;
background-color: red;
}
.aside{
position: fixed;
left: 0;
top: 50%;
}
style>
<div class="aside">
<div class="item active">男装div>
<div class="item">女装div>
<div class="item">童装div>
<div class="item">鞋帽div>
div>
<div class="content">
<div class="neirong content1">男装div>
<div class="neirong content2">女装div>
<div class="neirong content3">童装div>
<div class="neirong content4">鞋帽div>
div>
<script>
//1.获取元素
let items=document.querySelectorAll('.item')
let neirongs=document.querySelectorAll('.neirong')
//2.aside点击谁谁高亮
for (let i = 0; i < items.length; i++) {
items[i].addEventListener('click',function(){
//找到上一个active类,移除
document.querySelector('.aside .active').classList.remove('active')
//点击谁,谁添加类
this.classList.add('active')
//3.右侧内容跟随走动
// //获取盒子的位置
// console.log(neirongs[i].offsetTop);
document.documentElement.scrollTop=neirongs[i].offsetTop
})
}
script>
clientWidth
和clientHeight
:当前可视区域,不包含边框和滚动条获取元素的可见部分的宽高(不包含边框,滚动条等)
let div=document.querySelector('div')
//不包含边框,滚动条等
console.log(div.clientWidth)//83不带单位
console.log(div.clientHeight)//100不带单位
//得到窗口宽高,并且当宽度变化时背景颜色变色
window.addEventListener('resize',function(){
let w=document.documentElement.clientWidth
if(w<200) document.body.style.backgroundColor='skyblue'
else if(w<400) document.body.style.backgroundColor='pink'
else if(w<800) document.body.style.backgroundColor='red'
else document.body.style.backgroundColor='green'
console.log('页面宽度:'+document.documentElement.clientWidth);
console.log('页面高度:'+document.documentElement.clientHeight);
})
需求:
①小图标鼠标经过事件
鼠标经过小图片,当前高亮,其余兄弟变淡,添加类
②大图片跟随变化
对应的大图片跟随显示,如果想要过度效果,可以使用opacity效果,可以利用CSS淡入淡出的效果,还是添加类
③左右侧按钮播放效果
点击右侧按钮,可以自动播放下一张图片
需要一个变化量index不断自增,然后播放下一张图片,如果到最后一张图片,必须要还原为第一张图片:索引号=索引号%数组长度(放到播放前面)
因为左右侧按钮有大量相同的操作,可以封装一个函数common
④解决一个BUG
点击右侧按钮可以实现播放下一张,但是鼠标经过前面的,播放就会乱序
解决方案:让变化量(索引号)重新赋值为当前鼠标经过的索引号
⑤开启定时器
定时器自动播放,相当于点击右侧按钮,只需right.click()
⑥鼠标经过停止定时器(清除定时器),鼠标离开开启定时器(开启定时器)
let timer=setTimeout(回调函数,等待的毫秒数)
clearTimeout(timer)//停止延迟函数
让代码延迟执行的函数,setTimeout仅仅执行一次,平时省略window
function Hello(){
alert('Hello')
}
//提前结束延迟函数
//clearTimeout(timer)
let timer=setTimeout(Hello,3000)//3秒后执行
let clock=document.querySelector('.clock')
function myInterval(){
let d=new Date()
clock.innerText=d.toLocaleString()
//延迟任务,自动调用,1秒后执行
setTimeout(myInterval,1000)
}
myInterval()
JavaScript一大特点就是单线程,即同一时间只能做一件事。这时因为JavaScript这门脚本语言诞生时的使命所致——JavaScript是为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对某个DOM元素进行添加和删除操作,不能同时进行。应该先进行添加,之后再删除
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是:如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
为了解决这个问题,利用多核CPU的计算能力,HTML5提出 web Worker 标准,允许JavaScript脚本创建多个线程。于是,JS中出现了同步和异步。
同步:即任务之间有顺序,前一个任务结束后再执行后一个顺序。
异步:即在做一个任务的期间可以同时一时间再做其他任务。
同步任务:所有的同步任务都在主线程上执行,形成一个执行栈。
异步任务:JS的异步是通过回调函数实现的
一般而言,异步任务有以下三种类型:
1、普通事件,如click、resize等
2、资源加载,如 load、error等
3、定时器,包括setlnterval、setTimeout等
异步任务相关添加到任务队列中(任务队列也称为消息队列)
1.先执行执行栈中的同步任务。
2.异步任务放入任务队列中。
3.一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
console.log(111)
setTimeout(function(){
console.log(222);
},0)
console.log(333)
// 执行结果:
// 111
// 333
// 222
由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环(event loop)
location的数据类型是对象,它拆分并保存了URL地址的各个组成部分
常用属性和方法:
//得到url地址,给的地址是字符串,可以使用js的方式跳转页面
console.log(location.href)
location.href='http://www.baidu.com'//跳转到百度
<a href="http://www.baidu.com">登录成功,<span style="color: red;">5</span>秒之后跳转页面至百度</a>
<script>
let span=document.querySelector('span')
let count=5
let Timer=setInterval(function(){
count--
span.innerHTML=`${count}`
if(count==0){
clearInterval(Timer)
location.href='http://www.baidu.com'
}
}, 1000)
</script>
43.form.html
<form action="44.target.html"><!--提交后跳转页面-->
<input type="text" name="username">
<button>提交</button>
</form>
输入:123
44.target.html
//获取43文件提交的信息
console.log(location.search)
输出结果:?username=123
<a href="#one.html">第一个</a>
<a href="#two.html">第二个</a>
<script>
console.log(location.hash);
//输出结果:点击第一个超链接,输出#one.html;点击第二个超链接,输出#two.html
//并且页面地址最后会改变,
//file:///D:/Javascript/45.location.hash.html#one.html
//file:///D:/Javascript/45.location.hash.html#two.html
</script>
后期学习vue路由的铺垫,经常用于不刷新页面,显示不同页面,比如网易云音乐
<button>刷新button>
<script>
let btn=document.querySelector('button')
btn.addEventListener('click',function(){
//刷新按钮,有本地缓存
location.reload()
//强制刷新,和ctrl+f5一样,直接更新最新内容,从网络获取
location.reload(true)
})
script>
location的数据类型是对象,该对象下记录了浏览器自身的相关信息
通过userAgent检测浏览器的版本及平台
//检测userAgent(浏览器信息)
!(function (){
const userAgent = navigator.userAgent
//验证是否为Android或iPhone
const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)
const iphone = userAgent.match(/(iPhone\sos)ls([id_]+)/)
//如果是Android或iPhone,则跳转至移动站点
if (android || iphone)
location.href = 'http://www.baidu.com'
})()
history 的数据类型是对象,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
history对象 | 作用 |
---|---|
back() | 可以后退功能 |
forward() | 前进功能 |
go(参数) | 前进后退功能,参数为1是前进一个页面,-1是后退一个页面 |
history对象一般在实际开发中比较少用,但是会在一些OA办公系统中见到
<button class="forward">前进button>
<button class="back">后退button>
<script>
let forward=document.querySelector('.forward')
let back=document.querySelector('.back')
forward.addEventListener('click',function(){
// history.forward()
history.go(1)
})
back.addEventListener('click',function(){
// history.back()
history.go(-1)
})
script>
swiper是一个开源、免费、强大的触摸滑动插件。这样我们可以不需要自己一步步编写轮播图等一些常用的功能,而可以直接使用swiper插件。学习如何使用插件
插件:就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果
学习插件的基本过程
熟悉官网,了解这个插件可以完成什么需求:https: //www.swiper.com.cn/
看在线演示,找到符合自己需求的demo https://www.swiper.com.cn/demo/index.html
查看基本使用流程https:// www.swiper.com.cn/usage/index.html
查看APi文档,去配置自己的插件https:// www.swiper.com.cn/api/index.html
下载插件后,解压找到swiper-bundle.js和swiper-bundle.css以及swiper-bundle.min.js、swiper-bundle.min.css。其中前两个是自己使用查询看的,后两个是实际使用时用的,因为压缩过,更小。将这两个文件复制放入代码文件夹中的css文件夹和js文件夹中
若无法上网,也可以直接点击demos文件夹,里面存放了demo的代码
注意:多个swiper同时使用的时候,类名需要注意区分
DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Swiper demotitle>
<meta name="viewport"content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"/>
<link rel="stylesheet" href="css/swiper-bundle.min.css"/>
<style>
.box{
width: 1000px;
height: 600px;
margin: 0 auto;
}
html,
body {
position: relative;
height: 100%;
}
body {
background: #eee;
font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
font-size: 14px;
color: #000;
margin: 0;
padding: 0;
}
.swiper {
width: 100%;
padding-top: 50px;
padding-bottom: 50px;
}
.swiper-slide {
background-position: center;
background-size: cover;
width: 600px;
height: 400px;
}
.swiper-slide img {
display: block;
width: 100%;
}
style>
head>
<body>
<div class="box">
<div class="swiper mySwiper">
<div class="swiper-wrapper">
<div class="swiper-slide">
<img src="./image/1.jpg" />
div>
<div class="swiper-slide">
<img src="./image/2.jpg" />
div>
<div class="swiper-slide">
<img src="./image/3.jpg" />
div>
<div class="swiper-slide">
<img src="./image/4.jpg" />
div>
<div class="swiper-slide">
<img src="./image/5.jpg" />
div>
div>
<div class="swiper-pagination">div>
div>
div>
<script src="js/swiper-bundle.min.js">script>
<script>
var swiper = new Swiper(".mySwiper", {
effect: "coverflow",
grabCursor: true,
centeredSlides: true,
slidesPerView: "auto",
coverflowEffect: {
rotate: 50,
stretch: 0,
depth: 100,
modifier: 1,
slideShadows: true,
},
pagination: {
el: ".swiper-pagination",
},
});
script>
body>
html>
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。
1、数据存储在用户浏览器中
2、设置、读取方便、甚至页面刷新不丢失数据
3、容量较大,sessionStorage和localStorage约5M左右
// 存储数据:
// localStorage.setItem(key,value)
localStorage.setItem('uname','张三')
// 获取数据:
// localStorage.getItem(key)
localStorage.getItem('uname')
console.log(localStorage.getItem('uname'))
// 删除数据:
// localStorage.removeItem(key)
localStorage.removeItem('uname')
可以按F12,查看应用->本地存储
本地存储只能存储字符串,无法存储复杂数据类型,需要将复杂数据类型转换成JSON字符串,再存储到本地
let obj={
uname:'张三',
age:30,
gender:'男'
}
// 存储数据:
// JSON.stringify(复杂数据类型):将复杂数据类型转换成 JSON字符串存储到本地
// console.log(JSON.stringify(obj))
// 输出结果:{"uname":"张三","age":30,"gender":"男"}
localStorage.setItem('obj',JSON.stringify(obj))
// 取出数据:
// JSON.parse(JSON字符串):将JSON字符串转换成对象,取出时使用
// localStorage.getItem('obj')
console.log(JSON.parse(localStorage.getItem('obj')))
JSON属性和值都是双引号进行包含。
需求:改为本次存储版本的学习信息表分析:
①读取本地存储数据(封装函数)
如果本地存储有数据,则返回JSON.parse()之后的对象
如果本地存储没有数据,则默认写入三条数据,注意存储的利用JSON.stringify()存储JSON格式的数据
②渲染模块
先读取本地存储数据,然后渲染
③添加模块
注意,先取的最新的本地存储数据,然后追加。新增了数据,要把新数据存储到本地存储别,忘记转换
④删除模块
先读取本地存储数据,删除数组元素后再更新到本地存储,然后渲染
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>Documenttitle>
<style>
*{
margin: 0;
padding: 0;
}
input{
width: 70px;
border: 1px solid skyblue;
}
select{
border: 1px solid skyblue;
}
button{
width: 40px;
color: white;
background-color:teal;
border-radius: 5px;
}
h2{
margin-top: 20px;
text-align: center;
}
table{
text-align: center;
width: 700px;
border: 1px solid skyblue;
border-collapse: collapse;
}
tr,th,td{
height: 50px;
border: 1px solid teal;
}
th{
background-color: skyblue;
}
tbody tr:hover{
background-color: #eee;
}
a {
text-decoration: none;
color: teal;
}
.add{
width: 700px;
margin: 0 auto;
}
style>
head>
<body>
<div class="add">
<h2>新增学生h2><br>
姓名:<input type="text" class="name">
年龄:<input type="text" class="age">
性别:<select name="gender" class="gender">
<option value="男">男option>
<option value="女">女option>
select>
薪资:<input type="text" class="salary">
就业城市:<input type="text" class="city">
<button class="add_btn">录入button>
<h2>学生信息表h2>
<table>
<thead>
<tr>
<th>学号th>
<th>姓名th>
<th>年龄th>
<th>性别th>
<th>薪资th>
<th>就业城市th>
<th>删除th>
tr>
thead>
<tbody>
tbody>
table>
div>
<ul>
ul>
<script>
// 从本地存储中取数据,封装为函数
function getLocalDate(){
let data=localStorage.getItem('data')
//若有数据则转换类型
if(data&&data!='[]')
return JSON.parse(data)
//若没有数据则默认写入一条数据
else{
let student=[
{id:1001,name:'张三',age:20,gender:'男',salary:'20',city:'北京'},
{id:1001,name:'李四',age:20,gender:'女',salary:'25',city:'广州'},
]
localStorage.setItem('data',JSON.stringify(student))
}
}
// getLocalDate()
let tbody=document.querySelector('tbody')
//根据数组进行渲染
function showTable(){
//获取本地数据
let student=getLocalDate()
//先删除以前的数据
tbody.innerHTML=''
//再渲染新的数据
for(let i=0;i<student.length;i++)
{
//创建tr
let tr=document.createElement('tr')
//tr内的内容
tr.innerHTML=`
${student[i].id}
${student[i].name}
${student[i].age}
${student[i].gender}
${student[i].salary}
${student[i].city}
${i}">删除
`
//给删除添加id以方便删除时获取id
tbody.appendChild(tr)
}
}
showTable()
//添加学生
//获取提交按钮
let add_btn=document.querySelector('.add_btn')
//获取各个表单元素
let name=document.querySelector('.name')
let age=document.querySelector('.age')
let gender=document.querySelector('.gender')
let salary=document.querySelector('.salary')
let city=document.querySelector('.city')
//添加点击提交事件
add_btn.addEventListener('click',function(){
let student=getLocalDate()
//若非空则添加到数组
if(Empty(name.value)&&Empty(age.value)&&Empty(gender.value)&&Empty(salary.value)&&Empty(city.value)){
let stuId
if(student.length!=0)
stuId=student[student.length-1].id+1
else//若数组为空,则学生学号从1001开始
stuId=1001
student.push({
id: stuId,//最后一个元素的Id+1
name: name.value,
age: age.value,
gender: gender.value,
salary: salary.value,
city: city.value
})
//将数组更新到本地
localStorage.setItem('data',JSON.stringify(student))
//重新渲染函数
showTable()
//将表单恢复为空
name.value=age.value=salary.value=city.value=''
gender.value='男'
}
}
)
//判断input非空,之后可以使用正则
function Empty(value){
if(value.trim()!='') return true
else{
alert('添加学员数据不可为空')
return false
}
}
//事件委托进行删除
let del=document.querySelector('tbody')
del.addEventListener('click',function(e){
let student=getLocalDate()
// console.log(e.target.tagName)
// 点击的标签名,当为A时执行
if(e.target.tagName=='A'){
//获取id,比如点击第一个,则返回0,即a中id保存的是其在数组中的位置
//console.log(e.target.id);
student.splice(e.target.id,1)
localStorage.setItem('data',JSON.stringify(student))
//重新渲染页面
showTable()
}
})
script>
body>
html>
用于匹配字符串中字符组合的模式
作用:
(1)字符表达式语法
let 变量名=/表达式/
//变量名存储的是一个正则表达式的对象
eg:let x=/Hello World/
(2)判断是否符合规则的字符串
//表达式变量.test(要匹配的字符串)
let str='My name is PCGuo,Hello World'
let bl=x.test(str)
//输出:true
正则表达式具体学习看之前笔记