WebAPI

作用:通过使用js去操作html和浏览器

分类:

  1. DOM:文档对象模型
  2. BOM:浏览器对象模型

一、DOM基础

1.简介

(1)DOM

(Document Object Model)文档对象模型,是浏览器提供的一套专门用来操作网页内容的功能,即开发网页特效实现交互内容

(2)DOM树(文档树)

将HTML文档以树状结构直观表现出来,称之为DOM树,是描述网页内容关系的名词。

作用是用树状图表示了标签与标签之间的关系

(3)DOM对象

把网页内容当作对象处理,浏览器根据html标签生成js对象,所有标签属性都可以在这个对象上找到,修改这个对象的属性会自动映射到标签上。

所有对象的最上层,即DOM树的根上面还有一层,叫Document

document是DOM里提供的一个对象,网页所有内容都在document里面

<div>Hello</div>
<script>let d=document.querySelector('div')console.dir(typeof d)d.innerHTML='World'd.style.color='red'
</script>

2.获取DOM元素

即通过js选择标签再对其进行相关操作

(1)通过CSS选择器来获取(常用)
①选择匹配的第一个元素—querySelector
document.querySelector('css选择器')
//参数可以包含一个或多个css选择器,返回匹配的第一个元素,一个HTMLElement对象,若没有匹配到返回null
<div>Hello</div>
<div>Hello2</div>
<script>//获取元素,输入qs会自动生成let d=document.querySelector('div')console.log(d)//输出结果:<div>Hello</div>d.style.color='red'
</script>

②选择匹配多个元素—querySelectorAll
document.querySelectorAll('css选择器')
//参数可以包含一个或多个css选择器,返回多个元素,即NodeList对象集合
<div>Hello</div>
<div>Hello2</div>
<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获取的是一个数组,所以修改的时候需要进行遍历

(2)其他获取DOM方法(了解即可)
  • document.getElementsByTagName:获取页面上的某一种标签,获取的是一个选择集,不是数组,但是可以用下标的方式操作选择集里面的标签元素

  • document.getElementById:通过id获取标签,因为id只能使用一次,所以返回只有一个

  • document.getElementsByClassName:通过类名获取标签选择集

  • document.getElementsByName:通过name获取标签选择集

3.修改DOM元素内容

(1)document.write()方法

可以将文本追加到</body>前,并且文本中的标签也会被解析,这一块在Javascript基础已经学过。

(2)对象.innerText属性

将文本内容添加/更新到任意标签位置,但文本中的标签不会被解析

<div>Hello</div>
<script> //获取元素,输入qs会自动生成    let d=document.querySelector('div')d.innerText='<div>World</div>'
</script>输出结果:将div标签中的文字更新为
<div>World</div>
(3)对象.innerHTML属性

将文本内容添加/更新到任意标签位置,并且文本中的标签会被解析

<div>Hello</div>
<script> //获取元素,输入qs会自动生成    let d=document.querySelector('div')d.innerHTML='<div>World</div>'
</script>输出结果:将div标签中的文字更新为
World

4.修改DOM元素属性

(1)设置/修改元素常用属性

对象名.属性=值

<!--将百度超链接改为必应-->
<a href="https://www.baidu.com/">百度</a>
<script> //获取元素    let a=document.querySelector('a') a.innerHTML='必应'   //修改元素属性a.href="https://cn.bing.com"
</script>
(2)设置/修改元素样式属性
①通过style属性操作css
<div>Hello</div>
<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需要添加单位

②通过类名操作css

若修改的样式比较多,直接通过style修改比较繁琐,则可以通过css类名的形势去修改

<head>    <style>.box{color:white;width:300px;height: 200px;background-color:skyblue;}</style>
</head>
<body><div>Hello</div><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操作css
  • 追加一个类:元素.classList.add('类名')
  • 删除一个类:元素.classList.remove('类名')
  • 切换一个类:元素.classList.toggle('类名')
<div class='box'>Hello</div>
<script>let d=document.querySelector('.box')d.classList.add('a')d.classList.add('b')//结果:<div class="box a b">Hello</div>d.classList.remove('b')//结果:<div class="box a">Hello</div>d.classList.toggle('c')//结果:<div class="box a c">Hello</div>d.classList.toggle('c')//结果:<div class="box a">Hello</div>
</script>

toggle切换指的是如果查询没有该类名则加上,若有则删除

(3)设置/修改表单元素属性

表单很多情况也需要修改属性,比如输入密码时的小眼睛,点击可以看到密码,其本质就是将表单类型从密码转变为文本框

  • 获取:DOM对象.属性名
  • 设置:DOM对象.属性名=新值
<input type="text" value="请输入">
<botton disabled>提交</botton>
<input type="checkbox" class="check">
<script>// 1.获取元素let input=document.querySelector('input')// 2.取值或设置值,得到input中的值可以使用valueinput.type='password'// 启用按钮let btn=document.querySelector('botton')btn.disable=false//若等于true表示不能使用,若false表示可以启用//勾选复选框let checkbox=document.querySelector('.check')checkbox.checked=true
</script>

5.定时器-间歇函数

定时器在javascript中的作用:

  1. 制作动画
  2. 异步操作
  3. 函数缓冲与节流
  • setTimeout(函数,间隔时间) 只执行一次的定时器

  • clearTimeout(变量名) 关闭只执行一次的定时器

  • setInterval(函数,间隔时间) 反复执行的定时器

  • clearInterval(变量名) 关闭反复执行的定时器

    间隔时间是毫秒,1000毫秒=1秒

(1)举个栗子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-11let date = now.getDate();let week = now.getDay();//星期是从0-6let 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-6function 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>
(2)举个栗子2:协议倒计时
<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>

二、DOM事件

1.事件

(1)事件

事件是在编程时系统内发生的动作或者发生的事情

(2)事件监听:(注册事件)

让程序检测是否有事件,若有事件触发则立即调用一个函数做出响应,也称为注册事件

元素.addEventListener('事件',要执行的函数)

①事件监听三要素
  • 事件源:DOM元素被事件触发,需要获取DOM元素

  • 事件:用什么方式触发

    注:事件是字符串

    事件类型:

    1. 鼠标触发:

      1. click鼠标点击
      2. mousemove鼠标移动
      3. mouseover 鼠标进入(进入子元素也触发)
      4. mouseout 鼠标离开(离开子元素也触发)
      5. mouseenter 鼠标进入(进入子元素不触发)尽量使用这个
      6. mouseleave 鼠标离开(离开子元素不触发)尽量使用这个
      7. hover同时为mouseenter和mouseleave事件指定处理函数
      8. scroll 滚动条的位置发生变化
    2. 焦点事件:表单获得光标
      1. focus获得焦点
      2. blur失去焦点
      3. submit用户递交表单
    3. 键盘事件:键盘触发
      1. keydown键盘按下触发
      2. keyup键盘抬起触发
    4. 文本事件:表单输入触发
      1. input用户输入事件
    5. ready() DOM加载完成
    6. resize() 浏览器窗口的大小发生改变
  • 事件调用的函数:要做的事情

②举个栗子1:点击叉号关闭图片
<div class="imgbox"><img src="data:image/background.jpg"><div class="chahao" style="color: black;">x</div>
</div>
<script>let imgbox=document.querySelector('.imgbox')let chahao=document.querySelector('.chahao')chahao.addEventListener('click',function(){//隐藏盒子imgbox.style.display='none'})
</script>

③举个栗子2:小米输入框
  • 开始下拉菜单隐藏

  • 表单获得焦点就显示下拉菜单并将文本框变色

  • 表单失去焦点,反向操作

<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.获取元素//使用属性选择器选择searchlet 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>

④举个栗子3:微博输入
  • 不断取得文本框里面的字符长度
  • 把获得的数字给下面文本框,若字数为0或达到最多就将字数设置为红色
<div class="Weibo">有什么新鲜事想要告诉大家?<br><textarea placeholder="说点什么吧..." id="area" cols="30" rows="10" maxlength="200"></textarea><div class="foot"><span>0</span>/200<button>发布</button></div>
</div>
<script>let area=document.querySelector('#area')let text=document.querySelector('.foot span')let fontNum=0area.addEventListener('input',function(){fontNum=area.value.lengthtext.innerHTML=fontNumif(fontNum!=0&&fontNum<200)text.style.color='black'elsetext.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>红米K40</td><td>小米</td><td>¥1999</td></tr><tr><td><input type="checkbox" class="check2"></td><td>OPPO Findx3</td><td>OPPO</td><td>¥3000</td></tr><tr><td><input type="checkbox" class="check3"></td><td>Iphone13</td><td>苹果</td><td>¥6000</td></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=falsereturn}}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>

2.高阶函数

可以理解为函数的高级使用,把函数当作来对待的函数就是高级函数

(1)函数表达式

let 变量名=function(){}

(2)回调函数

如果将一个函数当作一个参数传递给另一个参数,那么当参数的函数称为回调函数。比较常见的是使用匿名函数当作回调函数

比如:checkAll.addEventListener('click',checkAllNum)中的checkAllNum就是回调函数

3.环境对象

环境对象指的是函数内部特殊的变量this,代表当前函数运行时所处的环境。目的是让代码更加简洁

this就是一个对象,普通函数this指向window,因为直接调用函数,相当于是window.函数,所以this指向window

function fn(){console.log(this)}
//结果:Window
btn.addEventListener('click',function(){console.log(this)})
//结果:<button>按钮</botton>

粗略的规则:谁调用,this就指向谁

//原来
btn.addEventListener('click',function(){btn.style.color='red'
})
//使用this
btn.addEventListener('click',function(){this.style.color='red'
})

4.排他思想

就是比如标签,只有选择的那一项会改变模样,其他不变,实现方法就是先将所有元素的样式关闭,然后只打开自己

for(let i=0;i<btns.length;i++)btns[i].addEventListener('chick',function(){// //干掉所有人// for(let j=0;j<btns.length;j++){//     btns[j].classList.remove('pink')//改进:因为只有一个会是pink样式,找到那唯一的一个pink类,然后删除document.querySelector('.pink').classList.remove('pink')//只打开自己this.classList.add('pink')}})

三、DOM节点

1.DOM节点

DOM树中的每个内容都称之为节点

(1)节点类型
  • 元素节点:标签
  • 属性节点:标签的属性
  • 文本节点:标签中的文本
(2)节点关系:
  • 父节点
  • 子节点
  • 兄弟节点

2.查找节点

<div class="a"><div class="b"><img src="" class="image"><div class="c"></div></div>
</div>
(1)查找父节点
  • 节点.parentNode:返回最近一级的父结点,找不到则返回null,若想找再上一层可以继续.parentNode
let image=document.querySelector('.image')
//查找父节点,得到<div class="b">...</div>
console.log(image.parentNode)
//查找父节点的父节点,得到<div class="a">...</div>
console.log(image.parentNode.parentNode)
(2)查找子节点
  • 节点.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)
(3)查找兄弟节点
  • 节点.nextElementSibling:查找下一个兄弟节点
  • 节点.previousElementSibling:查找上一个兄弟节点
//查找下一个兄弟节点,结果为:<div class="c"></div>
let next=image.nextElementSibling
console.log(next)
//查找上一个兄弟节点,结果为:<img src=(未知) class="image">
console.log(next.previousElementSibling)

3.增加节点

创建新的节点并放到指定位置

(1)创建节点—document.createElement('新的标签')
//创建标签
let d=document.createElement('div')
//添加class
div.className='d'
(2)追加节点
  • 插入到父元素的最后一个子元素后面—元素.appendChild(要插入的元素)
//追加到父元素最后一个子元素后面
let b=document.querySelector('.b')
b.appendChild(d)
//添加内容
d.innerHTML='class=d'
  • 插入到父元素中某个子元素的前面—元素.insertBefore(要插入的元素,在哪个元素前)
//追加到父元素第一个子元素前面
b.insertBefore(d,b.children[0])

在页面排列图片或者其他元素时,之前学的是用document.write(),这个方法并不好,因为需要在script内渲染,学到这里,我们就可以使用节点进行追加

(3)举个栗子:使用增加节点来实现之前的打印学生列表
<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>

4.克隆节点—元素.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')//克隆blet newb=b.cloneNode(true)//放到c的子节点let c=document.querySelector('.c')c.appendChild(newb)//放到最外层body内document.body.appendChild(newb)
</script>

5.删除节点—父元素.removeChild(要删除的孩子元素)

//删除刚才克隆到c内的b
c.removeChild(b)

四、时间对象

1.实例化

在代码中如果发现new关键字,一般将这个操作称为实例化

2.时间对象—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')

3.时间对象方法

时间对象返回的数据不能直接使用,需要使用一些方法进行转换格式

方法 作用 范围
getFullYear()
getMonth() 0~11
getDate()
getDay() 星期 0~6
getHours() 0~23
getMinutes() 0~59
getSeconds() 0~59

注:

月份是从0开始,所以需要加1;

星期是数字从0-6,所以需要转换成星期日、星期一、星期二、…、星期六

4.时间戳

时间戳是指从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);

五、重绘和回流

1.浏览器是如何进行界面渲染

  1. 解析(Parser)HTML,生成DOM树(DOM tree)
  2. 同时解析CSS,生成样式规则(Style Rules)
  3. 根据DOM树和样式规则,生成渲染树(Render Tree)
  4. 进行布局/Layout(回流/重排):根据生成的渲染树,得到节点的几何信息(位置、大小),即进行盒子布局
  5. 进行绘制/Painting(重绘):根据计算和获取的信息进行整个页面的绘制渲染相应的信息
  6. Display:展示在页面上

2.回流(重排)

当Render Tree中部分或者全部元素的尺寸、结构、布局发生改变时,浏览器就会重新渲染部分或者全部文档的过程称为回流

如:页面首次刷新;浏览器窗口大小发生改变;元素大小或位置发生改变;激活css伪类;DOM操作(如添加、删除DOM元素)

3.重绘

因为节点的样式发生改变,但是并不影响布局时,称为重绘

如:设置背景色、设置字体颜色等等

重绘不一定会引起回流,但是回流一定会引起重绘

四、DOM事件高级

1.事件对象

事件对象也是一个对象,存放事件触发时的相关信息。在事件绑定的回调函数的第一个参数就是事件对象,并且一般命名为event、ev、e,如鼠标点击事件中:元素.addEventListener('click',function(e){})事件对象e就存放了鼠标点击的位置等信息。可以使用console.log(e)查看事件对象详情

(1)事件对象常用属性
  • type:获取当前事件的类型

  • clientX/clientY:获取光标相对于浏览器可见窗口左上角的位置

  • offsetX/offsetY:获取光标相对于当前DOM元素左上角的位置

  • key:用户按下的键盘键的值

    • 注:现在不提倡使用keyCode

(2)举个栗子1:图片跟着鼠标移动
  1. 鼠标移动使用mousemove事件
  2. 不断将鼠标的坐标给图片的left和top值
<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>
(3)举个栗子2:回车发布微博,升级之前的微博发布
<!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>0</span>/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=0area.addEventListener('input',function(){fontNum=area.value.lengthtext.innerHTML=fontNumif(fontNum!=0&&fontNum<200)text.style.color='black'elsetext.style.color='red'})//按下回车生成留言信息let btn=document.querySelector('button')let ul=document.querySelector('ul')function btn_display(){if(area.value.trim()==''){area.value=''text.innerHTML=0alert('内容不能为空')return} else{let li=document.createElement('li')ul.insertBefore(li,ul.children[0])li.innerHTML=area.valuearea.value=nulllet 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+':'+mintext.innerHTML=0text.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>

2.事件流

指事件完整执行过程中的流动路径,先捕获,然后冒泡

  1. 捕获阶段:Document->HTML->body->div(即父到子)
  2. 冒泡阶段:div->body->html->Document(即子到父)

(1)事件冒泡阶段

当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称之为事件冒泡。

即:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件

<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上级还有相同的事件也会触发,若不同事件则不会被触发。

事件冒泡是默认存在的

(2)事件捕获阶段—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。即若开启捕获,则会从根元素开始去执行对应的事件。和冒泡正好相反。

捕获本身不重要,开发中基本不用,只用理解即可,主要是使用事件冒泡

(3)阻止事件流动

因为默认冒泡,那么容易导致事件影响到父级元素,若想让事件不影响父级元素,则需要阻止事件流动。阻止事件流动:在事件中: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()
})

此方法不仅可以阻断冒泡,还可以阻断捕获

之前学到的事件中

  1. mouseover 鼠标进入(有冒泡)
  2. mouseout 鼠标离开(有冒泡)
  3. mouseenter 鼠标进入(没有冒泡)
  4. mouseleave 鼠标离开(没有冒泡)

所以尽量使用mouseenter 鼠标进入和mouseleave 鼠标离开

(4)阻止默认行为—e.preventDeafult()

比如链接点击不跳转,表单域不提交

<a href="http://www.baidu.com">baidu</a>
<script>let a=document.querySelector('a')a.addEventListener('click',function(e){//点击链接不跳转,阻止默认行为e.preventDefault()})
</script>
(5)两种注册事件的区别:
  • 传统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(){}则不能解绑
      
    • 可以通过第三个参数去确定是在冒泡或者捕获阶段执行

3.事件委托

事件委托利用事件流的特征解决一些开发需求的知识技巧。

事件委托是利用事件冒泡的特点,给父节点添加事件,当点击子节点时会向上冒泡,冒泡到其父节点触发事件。即把子结点的事件委托给父节点,从而简化操作和提高性能

注:

  • 事件对象.target可以获得真正触发事件的元素,即子节点,是整个元素
  • 事件对象.target.tagName找到获得真正触发事件的元素标签名
  • 事件对象.target.id获取数据的索引号
<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li>
</ul>
<script>//不要每个li都注册事件,而是把事件委托给其父节点ullet ul=document.querySelector('ul')ul.addEventListener('click',function(e){//即通过冒泡性,点击其子结点时会向上冒泡,发现其父节点有点击事件,则会执行// alert('点击li')//得到点击的当前元素,即会得到li// console.log(e.target)//设置点击哪个li哪个li就变红e.target.style.color='red'})
</script>

4.举个栗子:学生管理案例

点击录入按钮,可以添加学生信息,主要目的是为了后面学习Vue做铺垫(数据驱动视图),即主要是操作数组数据,从而重新渲染页面

需求1:添加数据

  • 点击录入按钮,把表单内的值都放入数组内
  • 学号自动生成,若还未有学生,则从1001开始,若有学生则为数组最后一个学生的学号+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>Document</title><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++){//创建trlet tr=document.createElement('tr')//tr内的内容tr.innerHTML=`<td>${student[i].id}</td><td>${student[i].name}</td><td>${student[i].age}</td><td>${student[i].gender}</td><td>${student[i].salary}</td><td>${student[i].city}</td><td><a href="#" id="${i}">删除</a></td>`//给删除添加id以方便删除时获取idtbody.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 stuIdif(student.length!=0)stuId=student[student.length-1].id+1else//若数组为空,则学生学号从1001开始stuId=1001student.push({id: stuId,//最后一个元素的Id+1name: 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 trueelse{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>

5.举个栗子:手风琴特效

<!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;}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="data:image/1.jpg"><img src="data:image/2.jpg"><img src="data:image/3.jpg"><img src="data:image/4.jpg"><img src="data: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>

五、DOM网页特效

1.滚动和加载事件

(1)滚动事件—scroll

当页面进行滚动时触发,比如滚动时固定导航栏、或者点击按钮可以直接返回顶部

用到最多的就是监听整个页面滚动—window.addEventListener('scroll',function(){})

(2)加载事件—loadDOMContentLoaded
①load当资源加载完成触发

加载外部资源(如图片、外联CSS和Javascript等)加载完毕时触发事件。

有些时候需要等页面资源全部处理完了做一些事情;

或者老代码喜欢把script写到head中,这时候直接找DOM元素找不到

用到最多的就是监听所有资源加载完毕—window.addEventListener('load',function(){})

这个事件可以放到任何地方,因为是要等所有资源加载完毕才执行,但是还是提倡写在下面

②DOMContentLoaded当初始HTML文档被完全加载和解析完成触发

当初始HTML文档被完全加载和解析完成触,而无需等待样式表、图像等完全加载

2.元素大小和位置

掌握元素大小和位置的获取方式,为后续网页特效打基础

  • scroll家族

    • 获取元素内容的总大小
    • 获取元素向左向上滚出去看不见的距离可读写属性
  • offset家族

    • 获取元素自身大小:包括自身设置的宽高、padding、border
    • 获取元素距离定位父级的左和上距离只读属性
  • client家族

    • 获取元素可见区域的大小
    • 获取元素左、上边框距离只读属性
(1)scroll家族

比如我们想要页面滚动一段距离后就将一些元素显示或隐藏,那么就可以使用scroll来检测滚动距离

①获取宽高:scrollWidthscrollHeight:元素内容的总宽高,不包含滚动条

获取元素的内容总宽高(不包含滚动条)返回值不带单位

<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>
②获取位置:scrollLeftscrollTop

获取元素内容向左或者向上滚动出去看不到的距离,这两个属性是可以修改

//页面滚动事件
window.addEventListener('scroll',function(){//获取当前页面被卷去的头部let num=document.documentElement.scrollTop//可以修改,即只要一滚动那么会直接滚动到500documentElement.scrollTop=500console.log(num)
})window.addEventListener('scroll',function(){//获取当前页面被卷去的左边let num=document.documentElement.scrollLeftconsole.log(num)
})

document.documentElement是整个页面文档即<html>...</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>Document</title><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.scrollTopconsole.log(num)//当顶部向上滚动到500时显示返回顶部按钮if(num>=500)ret.style.display='block'elseret.style.display='none'})//点击返回事件ret.addEventListener('click',function(){document.documentElement.scrollTop=0})</script>
</body>
</html>

(2)offset家族

前面案例滚动多少距离,都是我们自己算的(如上面例子中的500),最好是页面滚动到某个元素,就可以做某些事。

简单说,就是通过js的方式,得到元素在页面中的位置这样我们可以做,页面滚动到这个位置,就可以返回顶部的小盒子显示。如当我们滑动到某个元素距离顶部多少像素时,显示返回顶部

①获取宽高:offsetWidthoffsetHeight:元素自身宽高,包含padding和border

获取元素的自身宽高、包含元素自身设置的宽高、padding、border

let div=document.querySelector('div')
//盒子的大小,和内容无关,包含padding、border
console.log(div.offsetWidth)//100不带单位
console.log(div.offsetHeight)//100不带单位
②获取位置:offsetLeftoffsetTop

获取元素距离自己定位父级元素的左、上距离,若父级没有定位则一层一侧向上找,直到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=0elseheader.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>
(3)client家族
①获取宽高:clientWidthclientHeight:当前可视区域,不包含边框和滚动条

获取元素的可见部分的宽高(不包含边框,滚动条等)

let div=document.querySelector('div')
//不包含边框,滚动条等
console.log(div.clientWidth)//83不带单位
console.log(div.clientHeight)//100不带单位
②resize事件:在窗口尺寸发生改变时触发
//得到窗口宽高,并且当宽度变化时背景颜色变色
window.addEventListener('resize',function(){let w=document.documentElement.clientWidthif(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);
})
(4)轮播图案例

需求:

①小图标鼠标经过事件

鼠标经过小图片,当前高亮,其余兄弟变淡,添加类

②大图片跟随变化

对应的大图片跟随显示,如果想要过度效果,可以使用opacity效果,可以利用CSS淡入淡出的效果,还是添加类

③左右侧按钮播放效果

点击右侧按钮,可以自动播放下一张图片

需要一个变化量index不断自增,然后播放下一张图片,如果到最后一张图片,必须要还原为第一张图片:索引号=索引号%数组长度(放到播放前面)

因为左右侧按钮有大量相同的操作,可以封装一个函数common

④解决一个BUG

点击右侧按钮可以实现播放下一张,但是鼠标经过前面的,播放就会乱序

解决方案:让变化量(索引号)重新赋值为当前鼠标经过的索引号

⑤开启定时器

定时器自动播放,相当于点击右侧按钮,只需right.click()

⑥鼠标经过停止定时器(清除定时器),鼠标离开开启定时器(开启定时器)


二、window对象学习内容

1.BOM(浏览器对象模型)

  • window是浏览器内置中的全局对象,我们所学习的所有Web APls的知识内容都是基于window对象实现的
  • window对象下包含了navigator、 location、document、history、screen 5个属性,即所谓的BOM(浏览器对象模型)
  • document是实现DOM的基础,它其实是依附于window的属性。
  • 注:依附于window对象的所有属性和方法,使用时可以省略window

2.定时器-延迟函数

let timer=setTimeout(回调函数,等待的毫秒数)
clearTimeout(timer)//停止延迟函数

让代码延迟执行的函数,setTimeout仅仅执行一次,平时省略window

function Hello(){alert('Hello')
}
//提前结束延迟函数
//clearTimeout(timer)
let timer=setTimeout(Hello,3000)//3秒后执行
延迟函数结合递归函数实现setInterval
let clock=document.querySelector('.clock')
function myInterval(){let d=new Date()clock.innerText=d.toLocaleString()//延迟任务,自动调用,1秒后执行setTimeout(myInterval,1000)
}
myInterval()

3.js执行机制:面试常见

(1)JS是单线程

JavaScript一大特点就是单线程,即同一时间只能做一件事。这时因为JavaScript这门脚本语言诞生时的使命所致——JavaScript是为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对某个DOM元素进行添加和删除操作,不能同时进行。应该先进行添加,之后再删除

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是:如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

(2)同步和异步

为了解决这个问题,利用多核CPU的计算能力,HTML5提出 web Worker 标准,允许JavaScript脚本创建多个线程。于是,JS中出现了同步和异步。

同步:即任务之间有顺序,前一个任务结束后再执行后一个顺序。

异步:即在做一个任务的期间可以同时一时间再做其他任务。

同步任务:所有的同步任务都在主线程上执行,形成一个执行栈

异步任务:JS的异步是通过回调函数实现的

一般而言,异步任务有以下三种类型

1、普通事件,如click、resize等

2、资源加载,如 load、error等

3、定时器,包括setlnterval、setTimeout等

异步任务相关添加到任务队列中(任务队列也称为消息队列

(3)JS执行机制–先同步后异步

1.先执行执行栈中的同步任务

2.异步任务放入任务队列中。

3.一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。

console.log(111)
setTimeout(function(){console.log(222);
},0)
console.log(333)
// 执行结果:
// 111
// 333
// 222

(4)事件循环

由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环(event loop)

4.location对象

location的数据类型是对象,它拆分并保存URL地址的各个组成部分

常用属性和方法:

(1)href 属性获取完整的URL地址,对其赋值时用于地址的跳转
//得到url地址,给的地址是字符串,可以使用js的方式跳转页面
console.log(location.href)
location.href='http://www.baidu.com'//跳转到百度
举个栗子:5秒后自动跳转页面
<a href="http://www.baidu.com">登录成功,<span style="color: red;">5</span>秒之后跳转页面至百度</a>
<script>let span=document.querySelector('span')let count=5let Timer=setInterval(function(){count--span.innerHTML=`${count}`if(count==0){clearInterval(Timer)location.href='http://www.baidu.com'}}, 1000)
</script>
(2)search属性获取地址中携带的参数,符号?后面部分

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
(3)hash 属性获取地址中的啥希值,符号#后面部分
<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路由的铺垫,经常用于不刷新页面,显示不同页面,比如网易云音乐

(4)reload方法用来刷新当前页面,传入参数true时表示强制刷新
<button>刷新</button>
<script>let btn=document.querySelector('button')btn.addEventListener('click',function(){//刷新按钮,有本地缓存location.reload()//强制刷新,和ctrl+f5一样,直接更新最新内容,从网络获取location.reload(true)})
</script>

5.navigator对象

location的数据类型是对象,该对象下记录了浏览器自身的相关信息

通过userAgent检测浏览器的版本及平台

//检测userAgent(浏览器信息)
!(function (){const userAgent = navigator.userAgent//验证是否为Android或iPhoneconst 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'
})()

6.history对象(了解)

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>

7.swiper插件

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 demo</title><meta name="viewport"content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"/><!-- Link Swiper's CSS --><link rel="stylesheet" href="css/swiper-bundle.min.css"/><!-- Demo styles --><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"><!-- Swiper --><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><!-- Swiper JS --><script src="js/swiper-bundle.min.js"></script><!-- Initialize Swiper --><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>

8.本地存储

随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。

1、数据存储在用户浏览器中

2、设置、读取方便、甚至页面刷新不丢失数据

3、容量较大,sessionStorage和localStorage约5M左右

(1)localStorage
  • 生命周期永久生效,除非手动删除否则关闭页面也会存在
  • 可以多窗口(页面)共享(同一浏览器可以共享)
  • 键值对的形式存储使用
①存储简单数据
// 存储数据:
// 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属性和值都是双引号进行包含。

(2)sessionStorage(了解)
  1. 生命周期为关闭浏览器窗口
  2. 在同一个窗口(页面)下数据可以共享
  3. 以键值对的形式存储使用
  4. 用法跟localStorage基本相同
(3)举个栗子:学生管理案例(本地存储版)

需求:改为本次存储版本的学习信息表分析:
①读取本地存储数据(封装函数)
如果本地存储有数据,则返回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>Document</title><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++){//创建trlet tr=document.createElement('tr')//tr内的内容tr.innerHTML=`<td>${student[i].id}</td><td>${student[i].name}</td><td>${student[i].age}</td><td>${student[i].gender}</td><td>${student[i].salary}</td><td>${student[i].city}</td><td><a href="#" id="${i}">删除</a></td>`//给删除添加id以方便删除时获取idtbody.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 stuIdif(student.length!=0)stuId=student[student.length-1].id+1else//若数组为空,则学生学号从1001开始stuId=1001student.push({id: stuId,//最后一个元素的Id+1name: 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 trueelse{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>

9.正则表达式

用于匹配字符串中字符组合的模式

作用:

  • 表单验证(匹配)
  • 过滤敏感词(替换)

(1)字符表达式语法

let 变量名=/表达式/
//变量名存储的是一个正则表达式的对象
eg:let x=/Hello World/

(2)判断是否符合规则的字符串

//表达式变量.test(要匹配的字符串)
let str='My name is PCGuo,Hello World'
let bl=x.test(str)
//输出:true

正则表达式具体学习看之前笔记

JS进阶webAPIs相关推荐

  1. js进阶 13-5 jquery队列动画如何实现

    js进阶 13-5 jquery队列动画如何实现 一.总结 一句话总结:同一个jquery对象,直接写多个animate()就好. 1.什么是队列动画? 比如说先左再下,而不是左下一起走 2.怎么实现 ...

  2. js进阶 10-8 伪类选择器有哪几类(自己不用,永远不是自己的)

    js进阶 10-8 伪类选择器有哪几类(自己不用,永远不是自己的) 一.总结 一句话总结:自己不用,永远不是自己的. 0.学而不用,却是为何? 自己不用,永远不是自己的,有需求的时候要想到它,然后操作 ...

  3. js进阶正则表达式15验证身份证号(|符号的使用:var reg=/^\d{17}[\d|X]$|^\d{15}$/)(str的方法substr)...

    js进阶正则表达式15验证身份证号(|符号的使用:var reg=/^\d{17}[\d|X]$|^\d{15}$/)(str的方法substr) 一.总结 1.|符号的使用:var reg=/^\d ...

  4. js进阶 11-22/23 js如何实现选项卡

    js进阶 11-22/23 js如何实现选项卡 一.总结 一句话总结:通过索引把选项卡头的li标签和选项卡内容的div标签联系在一起,通过控制div标签的display属性可以实现选项卡的选项切换. ...

  5. js进阶课程 12-9 jquery的事件对象event的方法有哪些?

    js进阶课程 12-9 jquery的事件对象event的方法有哪些? 一.总结 一句话总结:三组六个,阻止默认事件一组,阻止冒泡一组,阻止冒泡和剩余事件一组. 1.事件的默认动作指什么? 比如点a标 ...

  6. js进阶 13-6 jquery动画效果相关常用函数有哪些

    js进阶 13-6 jquery动画效果相关常用函数有哪些 一.总结 一句话总结:animate(),stop(),finish(),delat()四个. 1.stop()方法的基本用法是什么(sto ...

  7. js进阶 12-1 jquery的鼠标事件有哪些

    js进阶 12-1 jquery的鼠标事件有哪些 一.总结 一句话总结:1+3*2+1+1,其中里面有两组移入移出,一组和click,总结就是click(3个),hover(5个),mousemove ...

  8. js进阶正则表达式方括号(方括号作用)(js正则是在双正斜杠之中:/[a-z]/g)...

    js进阶正则表达式方括号(方括号作用)(js正则是在双正斜杠之中:/[a-z]/g) 一.总结 方括号:范围 圆括号:选 大括号:数量 1.js正则是在双正斜杠之中: var reg2=/[a-z]/ ...

  9. js进阶 12-8 如何知道鼠标和键盘当前操作的是哪个键

    js进阶 12-8 如何知道鼠标和键盘当前操作的是哪个键 一.总结 一句话总结:event.which属性. 1.如何获取事件发生的时间? timeStamp属性 event.timeStamp 属性 ...

最新文章

  1. 干货 | 请收下这份2018学习清单:150个最好的机器学习,NLP和Python教程
  2. 【项目实战】---使用ajax完毕username是否存在异步校验
  3. 浏览器标准模式与怪异模式的区别
  4. 使用java理解程序逻辑 第十二章_Java弱引用的理解与使用
  5. boost::gil::rgb8_image_t::recreate用法的测试程序
  6. swagger使用指南
  7. 数据库技术基础:查询优化相关知识笔记
  8. 使用BizTalk Server常见问题处理
  9. while/for 嵌套expect 批量免密码传文件
  10. 二进制转换 html,javascript 处理回传的二进制图像并显示在html上
  11. java异步判断数据库是否有重复字段值
  12. 网络空间搜索引擎ZoomEye
  13. 二级c语言考试改卷标准,计算机二级c语言考试技巧
  14. 中文转换成拼音实施方法
  15. 计算机三级网络技术(精简)
  16. HTML颜色编码和名称
  17. python turtle 乌龟赛跑_海龟快跑,turtle碰撞检测小游戏
  18. tplinkwr710n改无线打印服务器,TP-Link TL-WR710N V1无线路由器AP模式设置
  19. 2019中兴校招流程回顾总结
  20. ETL工具KETTLE常用设计之——作业设计思路模板

热门文章

  1. JVM优化之优化常用参数和工具
  2. 创业之前必须要做的八个测试(下)
  3. OKR如何用于「远程办公」?
  4. Opencv实现图片的油画特效
  5. 匿名类的定义,使用场景和使用方式
  6. Mac启动Openfire时提示“系统偏好设置错误”
  7. 感情沟通出了问题要怎么解决_感情出现问题怎么办
  8. 天融信VPN断电后web不能访问解决
  9. mongodb查询出指定的需要的字段
  10. matlab利用经纬度计算距离_【Matlab】根据经纬度计算两点间的球面距离