目录
Web API 基本认知
作用: 使用 JS 去操作 html 和浏览器
分类:DOM (文档对象模型) 和 BOM(浏览器对象模型)
DOM 基础知识
DOM
DOM(Document Object Model——文档对象模型):用来呈现以及与任意 HTML 或 XML文档交互的API,简单的说,DOM是浏览器提供的一套专门用来操作网页内容的功能
DOM的作用:开发网页内容特效和实现用户交互
DOM 树
DOM树:将 HTML 文档以树状结构直观地表现出来,我们称之为文档树或 DOM 树
DOM树的作用:直观地体现了标签与标签之间的关系
DOM 对象
DOM对象:浏览器根据 html 标签生成的 JS 对象
核心思想:把网页内容当做对象来处理
document 对象 :是 DOM 里提供的一个对象
注意:① 它提供的属性和方法都是用来访问和操作网页内容的 例:document.write()
② 网页所有内容都在document里面
DOM 基础操作
DOM 获取元素
方法一:*根据CSS选择器来获取DOM元素 *
① 选择匹配到的第一个元素
语法如下:
document.querySelector('css选择器')
//参数:包含一个或多个有效的CSS选择器字符串
//返回值:CSS匹配的第一个元素,一个HTMLElement对象,若没有匹配到,则返回null
举例如下:
<div>我是第一个盒子</div>
<div>我是第二个盒子</div>
<div class="three">我是第三个盒子</div>
<script>
let div1 = document.querySelector('div')
console.log(div1)
// 输出:我是第一个盒子
let div2 = document.querySelector('.three')
console.log(div2)
// 输出:我是第三个盒子
</script>
② 选择匹配到的多个元素
语法如下:
document.querySelectorAll('css选择器')
//参数:包含一个或多个有效的CSS选择器字符串
//返回值:CSS选择器匹配的 NodeList 对象集合
注意:① 该方法得到的是一个伪数组:有长度、有索引号的数组,但是没有 pop() 、push() 等数组方法
② 想要得到里面的每一个对象,则需要遍历(for)的方式获得
③ 哪怕只有一个元素,通过querySelectAll() 获取过来的也是一个伪数组,里面只有一个元素而已
举例如下:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
let lis = document.querySelectorAll('ul li')
console.log(lis)
// 输出:NodeList(3) [li, li, li]
// 通过遍历的方式,获得里面的每一个dom对象(元素)
for(let i = 0; i < lis.length; i++){
console.log(lis[i])
}
</script>
方法二:其他获取DOM元素的方法
//1.根据标签的id编号定位标签对应的DOM对象
let dom = document.getElementById('id内容')
//2.根据标签的class属性值定位标签对应的DOM对象
let domArray = document.getElementsByClassName('class属性内容')
//3.根据标签的类型定位标签对应的DOM对象
let domArray = document.getElementsByTagName('标签类型名')
//4.根据标签的name属性值定位标签对应的DOM对象
let domArray =document.getElementsByName('name属性内容')
DOM 设置/修改元素内容
方法一:document.write() 方法
特点:只能将文本内容追加到 </body> 前面的位置,文本中包含的标签会被解析
语法如下:
document.write('追加内容')
举例如下:
<div>旧内容</div>
<script>
document.write('新内容')
</script>
<!-- 页面显示: 旧内容
新内容
-->
方法二:元素.innerText 属性
特点:将文本内容添加/更新到任意标签位置,文本中包含的标签不会被解析
语法如下:
元素名.innerText = '添加内容'
举例如下:
<div>Javascript</div>
<script>
let div = document.querySelector('div')
div.innerText = '<h1>JS</h1>'
</script>
<!-- 页面显示:<h1>JS</h1> -->
方法三:元素.innerHTML 属性
特点:将文本内容添加/更新到任意标签位置,文本中包含的标签会被解析
语法如下:
元素名.innerHTML = '添加内容'
举例如下:
<div>Javascript</div>
<script>
let div = document.querySelector('div')
div.innerHTML = '<h1>JS</h1>'
</script>
<!-- 页面显示:JS -->
DOM 设置/修改元素属性
设置/修改常用属性
语法如下:
//获取对象
let 对象 = document.querySelector('css选择器')
//操作对象
对象.属性 = 值
设置/修改样式属性
① 通过 style 属性操作 CSS
语法如下:
//获取对象
let 对象 = document.querySelector('css选择器')
//操作对象
对象.syles.样式属性 = 值
注意:① 如果属性有 - 连接符,需要转换为小驼峰命名法,比如 要修改元素的padding-left,则 元素.style.paddingLeft = ‘修改的新值’
② 赋值的时候,需要的时候不要忘记加CSS单位
③ style属性只能获取和设置html里的行内样式,在类样式中定义的样式通过style获取不到
④ 由于body是唯一的标签,设置页面的整体样式(比如背景)时可以直接写 document.body.style
② 操作类名 (className) 操作 CSS
如果修改的样式比较多,直接通过style属性修改比较繁琐,我们可以通过借助于css类名的形式,新建一个目标样式的类名,然后进行赋值
语法如下:
//获取对象
let 对象 = document.querySelector('css选择器')
//操作对象
对象.classname = '目标样式的类名'
注意:① 由于class是关键字, 所以使用className去代替
② className是使用新值覆盖旧值, 如果仅仅需要添加一个类,并且还要保留之前的类名,需将原来的类名也写上去
③ 通过 classList 操作类控制CSS
为了解决 className 容易覆盖以前的类名,我们可以通过classList方式追加和删除类名,不影响之前的类名
语法如下:
//获取对象
let 对象 = document.querySelector('css选择器')
//操作对象
// 追加类
对象.classList.add('新类名')
// 删除类
对象.classList.remove('原类名')
// 切换类(有就去掉,没有就加上)
对象.classList.toggle('新类名/旧类名')
设置/修改表单属性
一般表单属性修改操作基本跟修改常用属性一致, 独有的表单属性添加就有效果,移除就没有效果,一律使用布尔值表示。如果为true,代表添加了该属性;如果是false,代表移除了该属性。eg: disabled、checked、selected
举例如下:
<input type="text" value="请输入">
<button disabled>按钮</button>
<input type="checkbox" name="" id="" class="checkBox">
<input type="radio" name="" id="" value="x" class="Radio"/>
<select name="" class="Select">
<option value="">1</option>
<option value="">2</option>
</select>
<script>
// 1. 获取input元素的内容
let input = document.querySelector('input')
// 取值或者设置值 得到input里面的值可以用 value
// console.log(input.value)
// 清空input里的值
input.value = ''
//转换为密码框,内容不可见
input.type = 'password'
// 2. 启用按钮
let btn = document.querySelector('button')
// disabled 不可用 = false 这样可以让按钮启用
btn.disabled = false
// 3. 勾选复选框
let checkbox = document.querySelector('.checkBox')
checkbox.checked = true
// 4. 勾选单选框
let radio = document.querySelector('.Radio')
radio.checked = true
// 5. 指定下拉列表默认项
let select = document.querySelector('.Select')
select[1].selected = true
</script>
DOM节点操作
DOM节点
DOM节点:DOM树里每一个内容都称之为节点
节点类型:① 元素节点( 所有的标签 比如 body、 div,html 是根节点)
② 属性节点(所有的属性 比如 href)
③ 文本节点(所有的文本)
④ 其他节点
查找节点
使用背景:可通过父节点、子节点、兄弟节点对目标节点进行定位,然后进行操作,比如点击 x 号关闭二维码(直接获取二维码图片对象即可,x号通过查找节点即可找到)等
父节点查找
// parentNode 属性
let 父节点 = 子元素.parentNode
//返回最近一级的父节点,找不到返回为null
子节点查找
① childNodes 属性
获得所有子节点、包括文本节点(空格、换行)、注释节点等
② *children 属性*
//children 属性
let 子节点集合 = 父元素.children
//返回的是一个伪数组,仅获得所有元素节点
兄弟节点查找
//下一个兄弟节点 nextElementSibling 属性
let 目标节点 = 此节点.nextElementSibling
//上一个兄弟节点 previousElementSibling 属性
let 目标节点 = 此节点.previousElementSibling
增加节点
使用背景:很多情况下,我们需要在页面中增加元素,比如,点击发布按钮,可以新增一条信息等
一般情况下,新增节点的操作如下:
①先创建:创建一个新的节点,然后进行节点样式设置
②后追加:把创建的新的节点放入到指定的元素内部
创建节点
//创建一个新的元素节点
let 新的节点 = document.createElement('标签名')
追加节点
①插入到父元素的最后一个子元素的后面
//插入到父元素中最后一个子元素的后面
父元素.appendChild(要插入的元素节点)
②插入到父元素中某个子元素的前面
//插入到父元素中某个子元素的前面
父元素.insertBefore(要插入的元素节点,目标子元素)
克隆节点
//克隆一个已有的元素节点
let 新的克隆节点 = 被克隆元素.cloneNode(布尔值)
//若为true,则代表克隆时会包含后代节点,一起克隆(深克隆)
//若为false(默认),则代表克隆时不包含后代节点(浅克隆)
删除节点
使用背景:若一个节点在页面中已不需要时,可以删除它,在 JavaScript 原生DOM操作中,要删除元素必须通过父元素删除
//删除节点
父元素.removeChild(子元素(要删除的元素))
注意:①如不存在父子关系则删除不成功
②删除节点和隐藏节点(display:none)有区别: 隐藏节点,节点还是存在html中的,但是删除节点,则从html中删除节点
事件基础
事件
事件:是在编程时系统内发生的动作或者发生的事情,比如用户在网页上单击一个按钮
事件监听:让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 注册事件
语法如下:
//建立事件监听
事件源.addEventListener('事件',要执行的函数)
事件监听三要素:
①事件源:被事件触发的dom元素
②事件:事件触发的方式,比如鼠标单击 click、鼠标经过 mouseover 等
③事件调用的函数:事件触发后实现的效果
注意:①事件类型要加引号
②函数是事件触发之后再去执行,每次触发都会执行一次
事件监听版本
//版本一:DOM L0
事件源.on事件 = function() { }
//版本二:DOM L2
事件源.addEventListener('事件',事件处理函数)
事件监听版本发展史 L:level(了解):
① DOM L0:是 DOM 的发展的第一个版本
② DOM L1:DOM级别1于1998年10月1日成为W3C推荐标准
③ DOM L2:使用addEventListener注册事件
④ DOM L3:DOM3级事件模块在DOM2级事件的基础上重新定义了这些事件,也添加了一些新事件类型
事件类型
鼠标事件
由鼠标触发,包含 click 鼠标点击、mouseenter 鼠标经过、mouseleave 鼠标离开
键盘事件
由键盘触发,包含 Keydown 键盘按下触发、Keyup 键盘抬起触发
焦点事件
由表单获得光标触发,包含 focus 获得焦点、blur 失去焦点
文本事件
由表单输入触发,包含 input 用户输入事件
事件进阶
事件对象
获取事件对象
事件对象:也是一个对象,这个对象里有事件触发时的相关信息 ,比如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
获取语法:
//获取事件对象
元素.addEventListener('事件',function(e){ })
在事件绑定的回调函数的第一个参数就是事件对象,一般命名为event、ev、e
事件对象常用属性
属性 | 含义 |
---|---|
type | 获取当前的事件类型 |
clientX/clientY | 获取光标相对于浏览器可见窗口左上角的位置 |
offsetX/offsetY | 获取光标相对于当前DOM元素左上角的位置 |
pageX/pageY | 获取光标相对于浏览器整个页面左上角的位置 |
key | 用户按下的键盘键的值(不提倡使用keyCode ) |
事件流
事件流介绍
事件流:事件完整执行过程中的流动路径,包括捕获阶段(从父到子)和冒泡阶段(从子到父 )
事件捕获和事件冒泡
事件冒泡:当目标元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发,这一过程被称为事件冒泡。简单的说就是,当一个元素触发事件后,会依次向上调用所有父级元素的同名事件。事件冒泡是默认存在的
举例如下:
<div class="father">
<div class="son"></div>
</div>
<script>
let fa = document.querySelector('.father')
let son = document.querySelector('.son')
fa.addEventListener('click', function () {
alert('我是爸爸')
})
son.addEventListener('click', function () {
alert('我是儿子')
})
document.addEventListener('click', function () {
alert('我是爷爷')
})
</script>
//点击'son'div,页面依次弹出'我是儿子' '我是爸爸' '我是爷爷'
事件捕获:从DOM的根元素开始去执行对应的事件 (从外到里)
事件捕获需要写对应代码才能看到效果,语法如下:
//事件捕获
触发事件元素.addEventListener('事件',事件处理函数,是否使用捕获机制)
举例如下:
<div class="father">
<div class="son"></div>
</div>
<script>
let fa = document.querySelector('.father')
let son = document.querySelector('.son')
fa.addEventListener('click', function () {
alert('我是爸爸')
},true)
son.addEventListener('click', function () {
alert('我是儿子')
},true)
document.addEventListener('click', function () {
alert('我是爷爷')
},true)
</script>
//点击'son'div,页面依次弹出'我是爷爷' '我是爸爸' '我是儿子'
注意:①addEventListener的第三个参数 传入true代表捕获阶段触发,传入false代表冒泡阶段触发,默认为false
②若是用 L0 事件监听,则只有冒泡阶段,没有捕获
阻止事件流动
使用背景:由于默认有冒泡模式的存在,所以容易导致同名事件影响到父级元素,若想把事件就限制在当前元素内,就需要阻止事件流动阻止事件流动需要拿到事件对象 语法: 此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
阻止事件流动需要拿到事件对象,语法如下:
//阻止事件流动
事件对象.stopPropagation()
举例如下:
<div class="father">
<div class="son"></div>
</div>
<script>
let fa = document.querySelector('.father')
let son = document.querySelector('.son')
fa.addEventListener('click', function () {
alert('我是爸爸')
})
son.addEventListener('click', function (e) {
alert('我是儿子')
//阻止流动
e.stopPropagation()
})
document.addEventListener('click', function () {
alert('我是爷爷')
})
</script>
//点击'son'div,页面只弹出'我是儿子'
//点击'father'div,页面依次弹出'我是爸爸' '我是爷爷'
注意: ① 鼠标经过事件: mouseover 和 mouseout 会有冒泡效果
mouseenter 和 mouseleave 没有冒泡效果(*推荐*)
②阻止默认行为,比如链接点击不跳转,表单域的不提交等
语法如下:
//阻止默认行为 事件对象.preventDefault()
举例如下:
<a href="http://www.baidu.com">百度</a> <script type="text/javascript"> let a = document.querySelector('a') a.addEventListener('click',function(e){ // 阻止默认行为、方法 e.preventDefault() }) </script> //点击百度,无法进行跳转
▶补充:* 两种注册事件的区别 *
传统on注册(L0) 事件监听注册(L2) 覆盖问题 同一个对象,后面注册的事件会覆盖前面注册的事件(同一个事件) 后面注册的事件不会覆盖前面注册的事件(同一个事件) 执行阶段 都是冒泡阶段执行的 可以通过第三个参数去确定是在冒泡或者捕获阶段执行 解绑问题 直接使用null覆盖就可以实现事件的解绑 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段) ,匿名函数无法被解绑
举例如下:
<button>点击</button> <script> let btn = document.querySelector('button') // 传统on注册(L0) // 多次相同的事件,只执行最后一次 btn.onclick = function () { alert('第一次') } btn.onclick = function () { alert('第二次') } //点击只弹出'第二次' // 解绑事件 btn.onclick = null // 事件监听注册(L2) btn.addEventListener('click', add) function add() { alert('第一次') } btn.addEventListener('click', function () { alert('第二次') }) //点击依次弹出'第一次' '第二次' // 解绑事件(必须使用removeEventListener事件,并且不能解绑匿名函数) btn.removeEventListener('click', add) </script>
事件委托
事件委托:是利用事件流的特征解决一些开发需求的知识技巧,事件委托其实是利用事件冒泡的特点, 给父元素添加事件(可以提高性能),子元素都可以触发,通过事件对象.target 可以获得真正触发事件的元素
举例如下:
<ul>
<li>我是第1个小li</li>
<li>我是第2个小li</li>
<li>我是第3个小li</li>
<li>我是第4个小li</li>
<li>我是第5个小li</li>
</ul>
<script>
//不需要对每个li进行注册事件 而是对ul进行注册事件
let ul = document.querySelector('ul')
ul.addEventListener('click', function (e) {
// 得到当前的元素
// console.log(e.target)
e.target.style.color = 'red'
})
</script>
//实现效果:点击谁谁变红
事件高级
滚动事件 scroll
滚动事件 scroll:当页面进行滚动时触发的事件
使用背景:很多网页需要检测用户把页面滚动到某个区域后做一些处理, 比如固定导航栏、返回顶部
语法如下:
// 页面滚动事件
window.addEventListener('scroll',function(){
//执行的操作
})
// 元素区域滚动事件
元素.addEventListener('scroll',function(){
//执行的操作
})
加载事件 load
加载事件 load:加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件
使用背景:有时候需要等页面资源全部加载完了才进行处理或者老代码喜欢把<script>写在<head>中,会导致 dom 元素找不到
语法如下:
// 页面加载完成事件
window.addEventListener('load',function(){
//执行的操作
})
// 元素加载完成事件
元素.addEventListener('load',function(){
//执行的操作
})
注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件
加载事件 DOMContentLoaded
加载事件 DOMContentLoaded:当初始的 HTML 文档被完全加载和解析完成之后,将触发DOMContentLoaded 事件,而无需等待样式表 、图像等完全加载
语法如下:
//监听页面DOM加载完成事件
document.addEventListener('DOMContentLoaded',function(){
//执行的操作
})
元素大小和位置 三大系列
scroll
使用场景:使用scroll 来检测页面滚动的距离
获取宽高:scrollWidth和scrollHeight 元素的内容总宽高(不包含滚动条),返回值不带单位
获取位置:scrollLeft和scrollTop 获取元素内容往左、往上滚出去看不到的距离,可 修改(赋值)
*开发中,经常检测页面滚动的距离,比如页面滚动xx像素,就可以显示一个元素,或者固定一个元素
举例如下:
window.addEventListener('scroll',function(){
// document.documentElement:HTML文档返回对象为HTML元素
// document.documentElement.scrollTop:当前页面被卷起的头部
let num = document.documentElement.scrollTop
if(num >= 目标距离){
//执行相关操作
}
})
offset
使用场景:希望页面滚动到某个元素,就可以做某些事,而不是自己计算距离,简单的说就是用offsetTop替代目标距离
获取宽高:offsetWidth和offsetHeight 获取元素的自身宽高、包含元素自身设置的宽高、padding、border,返回值不带单位
获取位置:offsetLeft和offsetTop 获取元素距离自己定位父级元素的左、上距离,是只读属性,不可直接修改(若无定位父级元素,则以文档左上角为准)
client
使用场景:窗口尺寸变化时可获取可视区域的宽高(resize事件)
获取宽高:clientWidth和clientHeight 获取元素的可见部分宽高(不包含边框,滚动条等),返回值不带单位
获取位置:clientLeft和clientTop 获取左边框和上边框宽度,是只读属性
*resize事件,代码如下:
//窗口尺寸改变时触发resize事件
window.addEventListener('resize',function(){
//执行的代码
})
举例如下:
//当窗口变化时改变页面背景颜色
window.addEventListener('resize',function(){
let w = document.documentElement.clientWidth
if(w>=1920){
document.body.style.backgroundColor = 'red'
}else if(w<540){
document.body.style.backgroundColor = 'hotred'
}else{
document.body.style.backgroundColor = 'deepred'
}
})
定时器
间歇函数
间歇函数:每隔一段时间需要自动执行一段代码,不需要我们手动去触发
间歇函数可以开启和关闭定时器:
① 开启定时器:每隔一段时间调用定时器内的函数
代码如下:
//开启定时器
//方法一:匿名间歇函数
setInterval(function(){
//函数体
},间隔时间毫秒数)
//方法二:具名间歇函数
function 函数名() {
函数体
}
setInterval(函数名,间隔时间毫秒数)
注意:①间隔时间单位是毫秒
②具名间歇函数调用时函数名不需要加括号
③定时器返回值是一个id数字,为定时器的序号
②关闭定时器:
代码如下:
//关闭计时器
let timerID = setInterval(函数,间隔时间毫秒数)
clearInterval(timerID)
注意:一般不会刚创建就停止定时器,而是满足一定条件再停止
延时函数
延时函数:JavaScript 内置的一个用来让代码延迟执行的函数,只执行一次
延时函数可以开启和关闭定时器:
① 开启定时器:等待一段时间后调用定时器内的函数
代码如下:
//开启定时器
//方法一:匿名延时函数
setTimeout(function(){
//函数体
},等待时间毫秒数)
//方法二:具名延时函数
function 函数名() {
函数体
}
setTimeout(函数名,等待时间毫秒数)
②关闭定时器:
代码如下:
//关闭计时器
let timerID = setTimeout(函数,等待时间毫秒数)
clearTimeout(timerID)
▶补充:* 结合递归函数可以使用 setTimeout 实现 setInterval 一样的功能 *
代码如下:
function Interval(){
// 执行的代码
// 延时任务进行自调用
setTimeout(Interval,1000)
}
// 启动定时任务
Interval();
BOM
BOM 基础认知
BOM(Browser Object Model——浏览器对象模型 ):window 是浏览器内置中的全局对象,所有 Web APIs 的知识内容都是基于 window 对象实现的,window 对象下包含了 navigator、location、document、history、screen 5个属性,即所谓的 BOM
注意:①依附于 window 对象的所有属性和方法,使用时可以省略 window
②document 是实现 DOM 的基础,它其实是依附于 window 的属性
location 对象
location 对象·:拆分并保存了 URL 地址的各个组成部分
常用属性和方法
属性(方法) | 作用 |
---|---|
href属性 | 获取完整的 URL 地址,对其赋值时用于地址的跳转 |
search属性 | 获取地址中携带的参数,符号 ?后面部分 |
hash属性 | 获取地址中的啥希值,符号 # 后面部分 |
reload()方法 | 用来刷新当前页面,传入参数 true 时表示强制刷新 |
举例如下:
// 得到当前文件的URL地址
console.log(location.href)
// 通过js方式跳转到目标地址
location.href = '目标URL地址'
// 得到当前文件的URL地址携带的参数
console.log(location.search)
// 得到当前文件的URL地址中的哈希值
console.log(location.hash)
// 刷新页面 (后期vue路由的铺垫,经常用于不刷新页面,显示不同页面)
location.reload()
// 强制刷新页面 类似与ctrl+F5
location.reload(true)
navigator 对象
navigator 对象:记录了浏览器自身的相关信息
常用属性和方法
通过 userAgent 检测浏览器的版本及平台,举例如下:
// 检测 userAgent(浏览器信息)
!(function () {
const userAgent = navigator.userAgent
// 验证是否为Android或iPhone
const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)
const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)
// 如果是Android或iPhone,则跳转至移动站点
if (android || iphone) {
location.href = 'http://m.itcast.cn'
}
})()
histroy 对象
history 对象:与浏览器地址栏的操作相对应,如前进、后退、历史记录等
常用属性和方法
方法 | 作用 |
---|---|
back() | 后退功能 |
forward() | 前进功能 |
go(参数) | 前进后退功能,参数如果是1,前进一个页面;如果是-1,后退一个页面 |
注意:history 对象一般在实际开发中比较少用,但是会在一些 OA 办公系统中见到
本地存储
本地存储特性
使用背景:随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据
本地存储特性如下:
① 数据存储在用户浏览器中
② 设置、读取方便、甚至页面刷新不丢失
③ 数据容量较大,sessionStorage和localStorage约 5M 左右
localStorage存储
localStorage存储语法如下:
//localStorage存储简单数据类型
//存储数据
localStorage.setItem('key','value')
//获取数据
localStorage.getItem('key')
//删除数据
localStorage.removeItem('key')
//localStorage存储复杂数据类型
//存储数据
localStorage.setItem('key',JSON.stringify(复杂数据类型))
//获取数据
JSON.parse(localStorage.getItem('key'))
//删除数据
localStorage.removeItem('key')
注意:本地存储只能存储字符串,所以存储复杂数据类型(Object对象)时, 一定要将复杂数据类型转换为json字符串再进行存储,取出时使用JSON.parse(),将json字符串转换为对象
localStorage特点:
① 生命周期永久生效,除非手动删除,否则关闭页面也会存在
② 可以多窗口(页面)共享(同一浏览器可以共享)
③ 以键值对的形式存储使用
sessionStorage存储
sessionStorage存储语法如下:(基本和localStorage相同)
//sessionStorage存储简单数据类型
//存储数据
sessionStorage.setItem('key','value')
//获取数据
sessionStorage.getItem('key')
//删除数据
sessionStorage.removeItem('key')
//sessionStorage存储复杂数据类型
//存储数据
sessionStorage.setItem('key',JSON.stringify(复杂数据类型))
//获取数据
JSON.parse(sessionStorage.getItem('key'))
//删除数据
sessionStorage.removeItem('key')
sessionStorage特点:
① 生命周期为关闭浏览器窗口
② 在同一个窗口(页面)下数据可以共享
③ 以键值对的形式存储使用
高阶函数
函数表达式
高阶函数可以被简单理解为函数的高级应用,JavaScript 中函数可以被当成数值、字符串、布尔、对象等来对待,基于这个特性实现函数的高级应用。
注意:① 普通函数的声明与调用无顺序限制,推荐做法先声明再调用
② 函数表达式必须要先声明再调用
回调函数
回调函数:如果将函数 A 作为参数传递给函数 B 时,我们称函数 A 为回调函数
当函数B被调用时,函数A才会被调用,具体代码如下:
// 具名函数作为回调函数
function 函数A(){}
函数B(函数A,参数1)
// 匿名函数作为回调函数
函数B(function (){
},参数)
注意:使用匿名函数做为回调函数比较常见
环境对象
环境对象:函数内部特殊的变量 this ,它代表着当前函数运行时所处的环境
this的指向:
①判断 this 指向的粗略规则:谁调用函数, this 就指代谁
②直接调用函数,其实相当于是 window.函数,故 this 指代 window
注意: 弄清楚this的指向,并且进行使用,可以让我们代码更简洁
编程思想
排他思想
排他思想:实现当前元素为A状态,其他元素为B状态
实现步骤:
①干掉所有人:使用for循环
②复活自己:通过this或者下标找到自己或者对应的元素
举例如下:
<style>
.pink {
background: pink;
}
</style>
<button>第1个</button>
<button>第2个</button>
<button>第3个</button>
<button>第4个</button>
<button>第5个</button>
<script>
let btns = document.querySelectorAll('button')
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function () {
// 干掉所有人
// 方法一
for (let j = 0; j < btns.length; j++) {
btns[j].classList.remove('pink')
}
// 方法二(推荐): 只需要找出那个唯一的 pink类,删除
document.querySelector('.pink').classList.remove('pink')
// 复活自己
this.classList.add('pink')
})
}
</script>
时间对象
实例化时间对象
时间对象:用来表示时间的对象,可以得到当前系统时间
实例化时间对象语法如下:
//获取当前时间
let date = new Date()
//获得指定时间
let date = new Date('xxxx-xx-xx')
时间对象方法
时间对象方法如下:
方法 | 作用 | 说明 |
---|---|---|
getFullYear() | 获得年份 | 获取四位年份 |
getMonth() | 获得月份 | 取值为 0 ~ 11 |
getDate() | 获取月份中的每一天 | 不同月份取值也不相同 |
getDay() | 获取星期 | 取值为 0 ~ 6 |
getHours() | 获取小时 | 取值为 0 ~ 23 |
getMinutes() | 获取分钟 | 取值为 0 ~ 59 |
getSeconds() | 获取秒 | 取值为 0 ~ 59 |
注意:调用getMonth()、getDay()方法时,记得+1
举例如下:
//将当前时间以:YYYY-MM-DD HH:mm 形式显示在页面
<style>
div {
width: 400px;
height: 50px;
background-color: pink;
text-align: center;
line-height: 50px;
}
</style>
<div></div>
<script>
let arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
let div = document.querySelector('div')
// 先调用,就省去了1秒的空白延迟期
getTime()
setInterval(getTime, 1000)
function getTime() {
let date = new Date()
let year = date.getFullYear()
let month = date.getMonth() + 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]}`
}
</script>
时间戳
时间戳:指1970年01月01日00时00分00秒起至现在的毫秒数,它是一种特殊的计量时间的方式
获取时间戳方式代码如下:
//使用 getTime() 方法
let date = new Date()
let timeStamp = date.getTime()
//简写 +new Date() (推荐)
let timeStamp = +new Date()
//使用 Date().now()
let timeStamp = Date().now()
注意:使用Date().now()无需实例化,但是只能得到当前的时间戳, 而其他两种可以返回指定时间的时间戳
补充:*倒计时转换公式*
倒计时总秒数 = (将来的时间戳 - 现在的时间戳)/ 1000
计算天数 d = parseInt(总秒数/ 60/60 /24)
计算小时 h = parseInt(总秒数/ 60/60 %24)
计算分数 m = parseInt(总秒数 /60 %60 )
计算当前秒数 s = parseInt(总秒数%60)
注意:通过时间戳得到是毫秒,需要转换为秒再计算
重绘和回流
浏览器进行界面渲染的过程
① 解析(Parser)HTML,生成DOM树(DOM Tree)
② 同时解析(Parser) CSS,生成样式规则 (Style Rules)
③ 根据DOM树和样式规则,生成渲染树(Render Tree)
④ 进行布局 Layout(回流/重排):根据生成的渲染树,得到节点的几何信息(位置,大小)
⑤ 进行绘制 Painting(重绘): 根据计算和获取的信息进行整个页面的绘制
⑥ Display: 展示在页面上
回流(重排)
回流(重排):当 Render Tree 中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的过程称为回流
重绘
重绘:由于节点(元素)的样式(比如:color、background-color、outline等)的改变并不影响它在文档流中的位置和文档布局时, 称为重绘
注意:*重绘不一定引起回流,而回流一定会引起重绘*
理解:会导致回流(重排)的操作 :
① 页面的首次刷新
② 浏览器的窗口大小发生改变
③ 元素的大小或位置发生改变
④ 改变字体的大小
⑤ 内容的变化(如:input框的输入,图片的大小)
⑥ 激活css伪类 (如::hover)
⑦ 脚本操作DOM(添加或者删除可见的DOM元素)
简单理解:影响到布局,就会有回流
正则表达式
正则表达式定义
正则表达式(Regular Expression):是用于匹配字符串中字符组合的模式
使用场景:验证表单(匹配)、过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等
正则表达式定义语法如下:
let 变量名 = /表达式/
//其中/ /是正则表达式字面量
正则表达式使用步骤:
①定义正则表达式
②检测查找是否匹配:test() 方法和exec() 方法
判断是否有符合规则的字符串
test() 方法:用来查看正则表达式与指定的字符串是否匹配,如果匹配 ,返回true,否则false
语法如下:
//判断是否有符合规则的字符串
regObj.test('被检测的字符串')
检索(查找)符合规则的字符串
exec() 方法:在一个指定字符串中执行一个首次搜索匹配,如果匹配成功,返回一个数组(包含首次出现符合规则的字符串的下标),否则返回null
语法如下:
//检索(查找)符合规则的字符串
regObj.exec('被检测的字符串')
元字符
元字符(特殊字符): 是一些具有特殊含义的字符,极大提高了灵活性和强大的匹配功能
元字符包含边界符、量词、字符类
边界符
边界符(位置符):用来提示字符所处的位置
边界符 | 说明 |
---|---|
^ | 表示匹配行首的文本(以谁开始) |
$ | 表示匹配行尾的文本(以谁结束) |
注意:如果 ^ 和 $ 在一起,表示必须是精确匹配,正则表达式和待检测字符串完全相同
量词
量词:用来设定某个模式出现的次数
量词 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复0次或一次 |
{n} | 重复n次 |
{n,} | 重复n或更多次 |
{n,m} | 重复n到m次 |
注意:①逗号左右两侧千万不要出现空格
② 量词只对最近的模式有效
字符类
① [ ] 匹配字符集合:后面的字符串只要包含[ ]中任意一个字符,都返回 true
② [ ] 里面加上 - 连字符:使用连字符 - 表示一个范围
③ [ ] 里面加上 ^ 取反字符:使用取反字符 ^ 表示范围之外
④ . 匹配除换行符之外的任何单个字符
⑤ 预定义:某些常见模式的简写方式,包含以下预定类:
预定类 | 说明 |
---|---|
\d | 匹配0-9之间的任一数字,相当于[0-9] |
\D | 匹配所有0-9以外的字符,相当于[^0-9] |
\w | 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_] |
\W | 除所有字母、数字和下划线以外的内容,相当于[^A-Za-z0-9_] |
\s | 匹配空格(包括换行符、制表符、空格符等),相等于[\t\r\n\v\f] |
\S | 匹配非空格的字符,相当于[^\t\r\n\v\f] |
修饰符
修饰符:用来约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等
语法如下:
/正则表达式/修饰符
//ignore 正则匹配时字母不区分大小写
/正则表达式/i
//global 匹配所有满足正则表达式的结果
/正则表达式/g
replace 替换,语法如下:
新的字符串 = 字符串.replace(/正则表达式/,'替换的文本')
举例如下:
<script type="text/javascript">
let str = 'abcdSbefgsbpjdsB'
//混合使用 g 和 i
str = str.replace(/sb/gi,'**')
console.log(str)
// 输出结果: abcd**efg**pjd**
</script>
JS 执行机制
JS 单线程
JavaScript 语言是单线程,也就是说,同一个时间只能做一件事,意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务,如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉
同步和异步
HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,因此JS 中出现了同步和异步
同步任务
同步任务都在主线程上执行,形成一个执行栈
异步任务
通过回调函数将异步任务添加到任务队列中(任务队列也称为消息队列)
一般而言,异步任务有以下三种类型:① 普通事件,如 click、resize 等② 资源加载,如 load、error 等③ 定时器,包括 setInterval、setTimeout 等
JS 执行机制
*JS 执行机制步骤*
注意:由于主线程不断重复获得任务执行任务、再获取任务再执行,所以这种机制被称为事件循环( event loop)
举例如下:
<script type="text/javascript">
console.log('1')
setTimeout(function () {
console.log('4')
}, 3000)
console.log('2')
setTimeout(function () {
console.log('3')
}, 0)
</script>
//输出: 1 2 3 4