JAVAScript进阶

114 阅读17分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

theme: fancy

15、加载事件

加载外部资源(如图片、外联CSSJavaScript等)加载完毕时触发的事件

\

事件名:load

window.addEventListener('load',function(){
//执行的操作
})

\

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

事件名:DOMContentLoaded

监听页面DOM加载完毕:

给document 添加DOMContentLoaded事件

document.addEventListener('DoMContentLoaded',function(){
//执行的操作
})

下面三种情况都会刷新页面都会触发load事件

1.a标签的超链接

2.F5或者刷新按钮

3.前进后退按钮

但是火狐浏览器中,有个特点是“往返缓存”,在这个缓存中不仅保存着页面数据,还保存了dom和javascript的状态;实际上是将整个页面都保存在了内存里。

所以此时后退按钮不能刷新页面。

此时可以使用pageshow事件来触发。这个事件在页面显示时触发,无论页面是否来自缓存。在重新加载页面中,pageshow会在load事件触发后触发;根据事件对象中的persisted来判断是否是缓存中的页面触发的pageshow事件,注意这个事件给window添加。

\

16、回流和重绘

16.1浏览器是如何进行界面渲染的

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

16.2回流(重排)

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

16.3重绘

节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、outline等),称为重绘。

PS:重绘不一定引起回流,而回流一定会引起重绘!!!

重绘和回流(重排)

·会导致回流(重排)的操作:

页面的首次刷新

浏览器的窗口大小发生改变k

元素的大小或位置发生改变

改变字体的大小

内容的变化(如:input框的输入,图片的大小)

激活css伪类(如::hover)

脚本操作DOM(添加或者删除可见的DOM元素)简单理解影响到布局了,就会有回流

17、事件冒泡

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

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

let fa=document.queryselector('.father')
let son=document.queryselector('.son')
fa.addEventListener('click',function(){
alert('我是爸爸')
})
son.addEventListener('click',function(){
alert('我是儿子')
})
document.addEventListener('dblclick',function(){
alert('我是爷爷')
})

PS:事件冒泡是默认存在的!


18、事件捕获

1.事件捕获概念:

从DOM的根元素开始去执行对应的事件(从外到里)

2.事件流概念:

事件流描述的是从页面中接收事件的顺序。事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。

事件捕获需要写对应代码才能看到效果

DoM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)

addEventListener第三个参数传入true代表是捕获阶段触发(很少使用)

若传入false代表冒泡阶段触发,默认就是false

若是用L0事件监听,则只有冒泡阶段,没有捕获

捕获和冒泡的区别在于执行的顺序相反,捕获和冒泡统称事件流

19、阻止事件流动

19.1阻止事件冒泡

Event.stopPropagation():

stopPropagation方法阻止事件流动,防止再触发定义在别的节点上的监听函数,

但是不包括在当前节点上其他的事件监听函数

19.2阻止事件的默认行为

Event.preventDefault():

Event.preventDefault Event.preventDefault方法取消浏览器对当前事件的默认行为。

比如点击链接后,浏览器默认会跳转到另一个页面,使用这个方法以后,就不会跳转了

20、事件委托

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

事件委托是给父级添加事件而不是全部孩子添加事件

优点:给父级元素加事件(可以提高性能)

原理:事件委托其实是利用事件冒泡的特点,给父元素添加事件,子元素可以触发

实现:事件对象.target可以获得真正触发事件的元素

21、this对象

this是一个对象,谁调用就指向谁,在设置一些表单组件的样式 中会比较好用

22、排他思想

当前元素为A状态,其他元素为B状态

使用:

1、干掉所有人

使用for循环

2、复活他自己

通过this或者下标找到自己或者对应的元素

<script>
let btns=document.querySelectorA11('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')
}
  //复活他自己
  this.classlist.add('pink')
})
}
</script>

效率更高的写法:

//只需要找出那个唯一的pink类,删除
document.querySelector('.pink').classList.remove('pink')
//我的
this.classList.add('pink')

\

23、BOM(浏览器对象)

23.1BOM简介

  • window 是浏览器内置中的全局对象,我们所学习的所有WebAPIs的知识内容都是基于window对象实现的
  • window 对象下包含了navigator、location、document、history、screen5个属性,即所谓的BOM(浏览器对象模型)
  • location.href 可以跳转到新的页面

语法:

location.href = '新的页面链接'

location.href = './index.html'
  • document是实现DOM的基础,它其实是依附于window的属性。
  • 注:依附于window 对象的所有属性和方法,使用时可以省略window

addEventListener('scrol1',function(){
console.log(111)
})
//可以直接省略window

24、利用递归实现setinterval

let div = document.querySelector('div')
function fn(){
div.innerHTML = new Date().toLocaleString()
setTimeout(fn,1000)
}
fn()

25、JS执行机制

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

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

25.1同步任务和异步任务

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

同步:

前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。

异步:

你在做一件事情时,因为这件事情会花费很长时阀,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。

同步和异步的本质区别:这条流水线上各个流程的执行顺序不同。

同步任务:

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

异步任务:

JS的异步是通过回调函数实现的。一般而言,异步任务有以下三种类型:

1、普通事件,如click、resize

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

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

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

25.2js执行机制

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

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

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

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

-- (event loop)。

26、window对象

26.1 location对象

window对象给我们提供了一个location属性用于获取或设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为location对象。

26.1.1URL

URL:统一资源定位符(Uniform Resource Locator,URL)是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

URL的一般语法格式:

protocol://host [:port]/path/[?query]#fragment

例: www.itcast.cn/index.html ?name=andy&age=18#1ink

26.1.2 location对象的属性

location对象属性 返回值
location.href 获取或者设置整个URL
location.host 返回主机(域名)www.itheima.com
location.port 返回端口号如果未写返回空字符串
location.pathname 返回路径
location.search 返回参数
location.hash 返回片段#后面内容常见于链接锚点

例:

var btn=document. querySelector(' button');
btn. addEventListener(' click', function(){
 location.href = "http://www. itcast. cn" ;
})

例:

第一个登录页面,里面有提交表单,action提交到index.html页面

第二个页面,可以使用第一个页面的参数,这样实现了一个数据不同页面之间的传递效果

第二个页面之所以可以使用第一个页面的数据,是利用了URL里面的location.search参数

在第二个页面中,需要把这个参数提取。

步骤:

第一步去掉?利用substr

第二步利用=号分割键和值split(=)

//1、先去掉? substr('起始的位置',截取几个字符)
var params =  location.search.substr(1);//uname = andy  省略第二哥参数会默认截取到最后一个
//2、利用=把字符串分割为数组 split('=')
var arr = params.split('=')

//arr[1]就是我们要的参数
var div = document.querySelector('div')
div.innerHTML = arr[i] + '欢迎您';

26.1.3location对象的方法

location对象方法 返回值

location.assign() |跟href一样,可以跳转页面(也称为重定向页面)

location.replace() 替换当前页面,因为不记录历史,所以不能后退页面

location.reload() 重新加载页面,相当于刷新按钮或者f5如果参数为true强制刷新ctrl+f5

例:

var btn=document. querySelector("button"); 
         btn. addEventListener('click', function(){
           //记录浏览历史,可以后退
         location. assign('http://www.itcast. cn');
           // location. replace('http://www.itcast. cn');
           //也可以实现跳转,但是不能后退
})

26.2 navigator对象

navigator对象包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值。

下面前端代码可以判断用户那个终端打开页面,实现跳转

26.3history对象

history的数据类型是对象,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等

history对象方法 作用

back() 可以后退功能

forward() 前进功能

go(参数) 前进后退功能参数如果是1前进1个页面如果是-1后退1个页面

history 对象一般在实际开发中比较少用,但是会在一些OA办公系统中见到。

houtui.addEventListener('click',function(){
history.back()
})

27、swiper 轮播图插件

插件:就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果学习插件的基本过程

熟悉官网,了解这个插件可以完成什么需求 www.swiper.com.cn/

看在线演示,找到符合自己需求的demo www.swiper.com.cn/demo/index.…

查看基本使用流程 www.swiper.com.cn/usage/index…

查看APi文档,去配置自己的插件 www.swiper.com.cn/api/index.h…

注意:多个swiper同时使用的时候,类名需要注意区分

27.1使用swiper

1、下载swiper

2、在工程中加入.CSS和.JS文件

3、在.html文件中链接这两个文件

<link rel="stylesheet"href="./css/swiper-bundle.min.css">
<script src="./js/swiper-bundle.min.js"></script>

4、按照demos文件夹中的html文件的结构在自己的html文件中粘贴到自己的html文件,也可以在浏览器打开后查看网页源代码复制结构 以及js,如:

27.2根据自己的喜好进行修改

看官网给的api文档,看每个属性对应的功能是啥,要怎么改

PS:swiper插件兼容多个框架

28、自定义属性

自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。

自定义属性获取是通过getAttribute('属性')获取。

但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。

H5规定自定义属性 data-开头 做为属性名 并且赋值

比如

<div data-index = '1'></div>

28.1获取元素的属性值

(1)element.属性

此方法可以获得元素内置的属性

(2)element.getAttribute('属性‘)

此方法即可获得元素的内置属性也可以获得自定义属性

<div getTime="20"></div>
<script>
var div = document.queryselector(' div');
//console. log(div. getTime);无法获取getTime属性
console.log(div. getAttribute('getTime'));//可以获取自定义属性

</script>

\

28.2设置元素的属性值

(1)element.属性='值'

此方法可以设置元素内置的属性

(2)element.setAttribute('属性','值');

此方法即可设置元素的内置属性也可以设置自定义属性,设置自定义属性时需要加data-前缀

div. setAttribute('index',2);
div. setAttribute('class','footer');//注意这里面写的就是class而不是className

(3) H5新增element.dataset.index 或者element.dataset['index'] ie 11才开始支持,这种方法可以获取或者设置内置属性也可以获取或者设置自定义属性,并且获取自定义属性时不需要加data-前缀,但要注意的是这种方法只能获取以data-开头的自定义属性

(4) 如果自定义属性里面有多个-链接的单词,我们获取的时候采取驼峰命名法

<div getTime="20" data-index="2|"data-list-name="andy"></div>
<script>
  console.log(div.dataset.listName);
  //或者
  console.log(div.dataset['listName']);
  </script>

28.3移除属性

div.removeAttribute('index');
//内置属性无法移除

29、本地存储

29.1本地存储特性

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

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

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

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

29.2localStorage

1、生命周期永久生效,除非手动删除否则关闭页面也会存在

2、可以多窗口(页面)共享(同一浏览器可以共享)

3.以键值对的形式存储使用

<1>存储数据:

<script>
localStorage.setItem('key',value)//key是字符串要加引号
//如
localStorage.setItem('uname','pink老师')//数据存在浏览器中任何一个浏览器都可以使用这个数据 
</script>

也可以存复杂数据类型如对象但必须以JSON格式传入

let obj = {
uname:'刘德华',
  age:17,
  address:'黑马程序员'
}
localstorage.setItem('obj',JSON.stringify(obj))

存储复杂数据类型存储

本地只能存储字符串,无法存储复杂数据类型.需要将复杂数据类型转换成JSON字符串,再存储到本地

JSON字符串格式:

属性和值都是双引号包含,如

let obj = {

"uname":"刘德华",

"age":"17",

"address":"黑马程序员"

}

JSON.stringify(复杂数据类型)

->将复杂数据转换成JSON字符串存储本地存储中

JSON.parse(JSON字符串)

->将JSON字符串转换成对象,取出时候使用

<2>获取数据(key值记得加引号):

localStorage.getItem(key)

也可以获取复杂数据类型如对象,但会以字符串形式传出,因此要将结果转成对象如

JSON.parse(localStorage.getItem('obj')) 

<3>删除数据(key值记得加引号): ,

localStorage.removeItem(key)

30、正则表达式

1.什么是正则表达式?

·正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。在Javascript中,正则表达式也是对象·通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式。

2.正则表达式有什么作用?

表单验证(匹配)

过滤敏感词(替换)

字符串中提取我们想要的部分(提取)

30.1正则表达式语法

30.1.1定义正则表达式

语法:

let 变量名 = /表达式/

比如:let reg = /前端/

30.1.2判断是否有符合规则的字符串

test()方法用来查看正则表达式与指定的字符串是否匹配

语法:

regObj.test(被检测的字符串)//注意是检测前面有没有包含在后面

比如

let str = 'IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训'
let reg = /前端/
let re = reg.test(str)//注意是检测前面有没有包含在后面
console.log(re)//true

如果正则表达式与指定的字符串匹配,返回true,否则false

30.1.3检索(查找)符合规则的字符串

exec( )方法,在一个指定字符串中执行一个搜索匹配

语法:

regObj.exec(被检测字符串)

比如

let str =  'IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训'
let reg = /前端/
let re = reg.exec(str)
console.log(re)//返回的是一个数组

如果匹配成功,exec()方法返回一个数组,并且可以看到索引号。否则返回null

30.2元字符(特殊字符)

元字符(特殊字符)是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。

比如,规定用户只能输入英文26个英文字母,普通字符的话 abcdefghijklm.……

但是换成元字符写法:[a-z]

30.2.1边界符

边界符(表示位置,开头和结尾,必须用什么开头,用什么结尾)

正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符

如果*和$在一起,表示必须是精确匹配

console.log(/^哈$/.test('我开心的哈哈大笑)) //false,必须以哈开头以哈结尾
console.log(/^哈/.test('我开心的哈哈大笑)) //false,必须以哈开头
 console.log(/^哈$/.test('哈哈'))//false,必须精确匹配,开头结尾不是同一个哈
 console.log(/^哈$/.test('哈'))//true

30.2.2量词

量词:用来设定某个模式出现次数

30.2.3字符类

在[]里面加上-连字符,表示一个范围

console.log(/^[a-z]$/.test('c'))//true

又如:

[a-z]表示 a到z 26个英文字母都可以

[a-zA-Z]表示大小写都可以

[0-9]表示0~9的数字都可以

^[1-9][0-9]{4,}$//表示开头一位必须是0~9,后面至少4位且取值范围是0~9
console.log(/^abc+$/.test('cc'))//+号只针对c有效,开头必须是abc可以出现多次,量词只对符号前面的一组数据有效
/[^a-zA-Z0-9-_]{6,16}$/ //表示由英文或数字、下划线或者短横线组成,并且长度为6~16位

3.字符类(比如\d表示0~9)

4.修饰符

修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等

语法:

/表达式/修饰符

i是单词ignore的缩写,正则匹配时字母不区分大小写

g是单词global的缩写,匹配所有满足正则表达式的结果

console.log(/a/i.test('a'))
console.log(/a/i.test('A'))

5.replace替换

语法:

字符串.replace(/正则表达式/,'替换的文本')

div.innerHTML = textarea.value.replace(/激情|基情/g,'**')

31、立即执行函数

不需要调用,代码运行到那里就自己执行

写法:

(function(){})()或者(function(){}())

在第一种写法中,最外面的小括号可以传入实参,而function后面的小括号可以传入形参,大括号里面还是写函数体,也就是说第二个小括号可以看做是调用函数

在第二中写法中,和第一种相似,后面的小括号传实参,前面的小括号传形参,大括号里面是函数体

PS:

1·立即执行函数后面要加分号;表示结尾

2·立即执行函数function后面也可以加函数名

//写法二
(function sum(a,b){
console.log(a+b);
}(2,3));
//写法一比较常用
(function sum(a,b){
console.log(a+b);})(2,3);

3·立即执行函数最大的作用就是独立创建了一个作用域 ,避免了命名冲突问题