javascript进阶
2022-09-19 12:46:09 # javascript

API

API(Application Programming Interface应用程序编程接口),是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而无需源码,或理解内部工作机制的细节

WEB API

是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM), 现阶段主要针对于浏览器讲解常用的API,主要针对浏览器做交互效果,MDN详细API:https://developer.mozilla.org/zh-CN/docs/Web/API

DOM

简介

  • 文档对象模型(Document Object Model),是W3C组织推荐的处理可扩展标记语言(html或者XML)的标椎

  • 编程接口.通过DOM接口可以改变网页的内容、结构和样式

  • 文档:一个页面就是一个文档,DOM中使用document表示

  • 元素:页面中的所有标签都是元素,DOM中使用element表示

  • 节点:网页中的所有页面都是节点(标签、属性、文本、注释等),DOM中使用node

获取元素

通过以下方式获得:

  1. 根据ID获取:getElementById()方法获取带有ID的元素对象:

    由于元素的 ID 在大部分情况下要求是独一无二的,这个方法自然而然地成为了一个高效查找特定元素 的方法。返回的是一个匹配ID的DOM的Element对象,若没有找到,就返回null,例如:

    1
    2
    3
    4
    5
    6
    <div id="time">2021</div>
    <script>
    //页面是从上向下加载的,所以先得有标签,才能在运行script中的内容
    var timer=document.getElementById('time'); //参数必须是字符串类型
    console.log(timer.value);//最后结果输出(完整标签)<div id="time">2021</div>
    </script>

    console.dir(timer)//打印 div#timer 属性和方法

  2. 根据标签获取:

    getElementsByTagName()方法可以返回带有指定标签名的对象的集合,返回过来的是 获取过来元素对象的集合 以伪数组的形式存储

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <ul>
    <li>hello1</li>
    <li>hello2</li>
    <li>hello3</li>
    <li>hello4</li>
    <li>hello5</li>
    </ul>
    <script>
    var cnt=document.getElementsByTagName('li');
    console.log(cnt[0]);//打印出 <li>hello1</li>
    </script>

    循环打印出所有li标签的内容

    1
    2
    3
    4
    5
    6
    7
    for(var i=0;i<(cnt.length);i++){
    console.log(cnt[i])
    }
    //或
    for(var t in cnt){
    console.log(cnt[t])
    }

    还可以获取某个元素(父元素)内部所有指定标签名的子元素:

    例如: 如何获取ol中的li,而不获取ul中的li?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<ul>
<li>hello1</li>
<li>hello1</li>
</ul>
<ol id='ol'>
<li>hello1</li>
<li>hello1</li>
</ol>
<script>
//方法一
var cnt=document.getElementsByTagName('ol');
console.log(cnt[0].getElementsByTagName('li'));
//方法二
var cnt=document.getElementById('ol');
console.log(cnt.getElementsByTagName('li'));
</script>

父元素必须是单个对象(必须指明是哪一个元素对象),获取的时候不包含父元素自己

以上方法为传统方式

  1. 通过HTML5新增的方法获取:

    1
    2
    3
    getElementsByClassName('类名'); //根据类名返回元素对象集合
    querySelector('选择器'); //根据指定选择器返回第一个元素对象,注意只能返回第一个元素对象,里面的选择器需要加符号(.demo #demo),也可以是标签选择器
    querySelectorAll('选择器'); //根据指定选择器返回所有元素对象,集合
  2. 特殊元素获取(body,html):

    获取body:document.body 不带参数

    获取html:document.documentElement 不带参数

事件基础

事件三要素/事件三部分:事件源、事件类型、事件处理程序

  1. 事件源:事件被触发的对象,谁->按钮
  2. 事件类型:如何触发,什么事件->鼠标点击(onclick) 鼠标经过 键盘按下 滑轮滚动等
  3. 事件处理程序:通过一个函数赋值的方式完成

例如一个简单的事件:

1
2
3
4
5
6
7
<button id="btn">example</button>
<script>
var btn=document.getElementById('btn');
btn.onclick=function(){ //匿名函数调用
alert('hello world');
}
</script>

执行事件的步骤:

  1. 获取事件源 var div=document.getSelecetor(‘div’)
  2. 注册事件(绑定事件) div.onclick
  3. 添加事件处理程序(采取函数赋值形式) div.onclick=fcuntion(){}

常见的鼠标事件:

  • onclick:左键触发
  • onmouseover:经过触发
  • onmouseout:离开触发
  • onfocus:焦点触发
  • onblur:失去焦点触发
  • onmousemove:移动触发
  • onmouseup:弹起触发
  • onmousedown:按下触发

操作元素

DOM可以改变网页的内容、结构和样式,利用DOM操作元素来改变元素里面的内容、属性等

直接调用时是获取元素的文本内容,例如demo.innerText
  1. 改变元素内容:

    element.innerText:从起始位置到终止位置的内容,但它去除HTML标签,同时空格和换行也会去掉,用的较少

    element.innerHTML:起始位置到终点位置的全部内容,包括HTML标签,同时保留空格和换行,用的较多

    上述只是对普通的盒子进行的,要想对表单元素进行设置,需要调用value,例如:input.value=‘xxx’

1
2
3
var div=document.querySelector('div');
div.innerText='xxx';
text[0].innerText +='hello' //追加内容
innerText输入的是文本,不能识别HTML,并且能够去除空格和标签;而innerHTML能够识别HTML,同时保留空格和换行
例如:div.innerHTML='<strong>今天是:</strong>2021'
推荐使用innerHTML(是一种标准)
  1. 常用元素的属性操作:

    1、innerText、innerHTML改变元素内容(普通盒子如div),innerHTML更常用
    2、src href
    3、id alt title

    图片切换小项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<button id="a">one</button>
<button id="b">two</button>
<img src="../CSS3/img/a.jpg" alt="no_img" title="girl">
<script>
var a=document.getElementById('a');
var b=document.getElementById('b');
var img=document.querySelector('img');
a.onclick=function(){
img.src='../CSS3/img/b.png';
img.title='man';
}
b.onclick=function(){
img.src='../CSS3/img/a.jpg';
img.title='girl';
}
</script>
  1. 表单元素的属性操作:

    利用DOM可以操作如下表单元素的属性: type value checked selected disabled(被禁用)

    表单里面的值 文字内容是通过value来修改的

1
2
3
4
5
6
example.value='xxxx';
btn.onclick=function(){
btn.disabled=true;//方法一,按钮禁用
this.disabled=true;//方法二,按钮禁用
//this指的是事件函数的调用者
}
  1. 样式属性操作:

    通过JS修改元素的大小、颜色、位置等样式

    1
    2
    element.style	//行内样式操作
    element.className //类名样式操作

    行内样式操作

    修改的样式很少时使用

    里面的属性名采用驼峰命名法,比如backgroundColor、fontSize等

    JS修改的style样式操作,产生的是行内样式,css权重比较高

    1
    2
    3
    4
    var dic=document.querySelector('div');
    div.onclick=function(){
    this.style.backgroundColor='purple'
    }

    小项目1:循环精灵图

    1
    2
    3
    4
    5
    6
    7
    <script>
    var lis=document.querySelectorAll('li');
    for(var i=0;i<lis.length;i++){
    var index=i*44;
    lis[i].style.backgroundPosition = '0 -'+index+'px';
    }
    </script>

    小项目2:显示隐藏文本框内容

    当修改的样式太多时,使用行内样式显得比较复杂

    类名样式操作

    先将要修改的样式提前声明一个样式类,然后再调用声明的样式this.className=‘change’

    className会直接更改元素的类型,会覆盖原先的类名

    如果想要保留原先的类,则:

    this.className=‘first change’

    在实际开发中,更推荐使用类名样式,这样在后期的维护中只需要修改类名中的内容即可,而不用去修改JS

    小项目:密码框格式提示错误信息:

    两种方式均可

5.排他思想

image-20220720210003035

当页面有多个按钮时,为每个按钮设置一个onclick会显得繁琐,这时最好用循环来做

1
2
3
4
5
6
7
8
9
10
11
12
<script>
var btns=document.getElementsByTagName('button');
for(var i=0;i<btns.length;i++){
btns[i].onclick=function(){
//在调用之前将所有其他的按钮背景颜色置空,在执行要改变的颜色
for(var i=0;i<btns.length;i++){
this.style.backgroundColor='';
}
this.style.backgroundColor='pink';
}
}
</script>

小项目1:百度换肤

小项目2:表格隔行变色的效果,不难,就不写了

小项目3:表单全选取消全选

6.自定义属性的操作

image-20220721184552893

第一种方式只能用于标签自带的属性值,而第二种可以调用用户自定义的属性

image-20220721185233936

1
2
//index为自定义属性,id为标签自带属性
<div id='demo' index='1'></div>

设置属性值:

image-20220721185932621

提倡标签自带的属性用第一种写,自定义的用第二种,只是提倡

移除属性:

image-20220721190048395

小项目:tab栏切换,京东做法 重要

image-20220721215708512

image-20220721215931036

getAttribute是没有兼容性问题的,第二种ie11才开始支持

注意一点:

1
2
3
4
5
6
7
<div data-list-name='xxx'></div>
<script>
var div=document.querySelector('div');
console.log(div.dataset-listName);
console.log(div.dataset['listName']);
</script>

data-list-name–>驼峰命名法–>listName

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

节点操作

image-20220721221839314

image-20220721222831040

image-20220721223058592

  1. 父级节点

image-20220722132615870

  1. 子节点

image-20220722132928003

image-20220722133121217

实际开发中更提倡使用上面一种方式,第一种方式包含了无用的节点

获取指定的节点:

image-20220722133405915

上面的方式会包含无用的节点

image-20220722133558468

上面的方式不包含无用的节点,但有兼容性问题,解决方案如下(实际开发中的):

image-20220722133937672

小项目:新浪下拉菜单

  1. 兄弟节点

image-20220722160325319

获取的是上、下一个兄弟节点,包括元素节点或者文本节点等等

image-20220722160414655

  1. 创建节点

image-20220722163003461

image-20220722163041556

后面追加元素

例如

1
2
3
4
5
6
<ul></ul>
<script>
var ul=document.querySelector('ul');
var li=document.createElement('li');
ul.appendChild(li);
</script>

image-20220722163601337

1
ul.insertBefore(li,ul.children[0]);

小项目:简单版发布浏览案例

  1. 删除节点

image-20220722172142091

小项目:删除留言案例

image-20220722174840322

1
2
3
<a href='javascript:void(0);'> </a>
//或
<a href='javascript:;'> </a>

不要忘记后面的分号

  1. 复制节点

image-20220722210247738

这样只是复制了一份节点,还需要将其放到结构中去

1
2
3
var ul=document.querySelector('ul');
var clone_li=ul.children[0].cloneNode();
ul.appendChild(clone_li);

可以用appendChild或者insertBefore

image-20220722211221343

小项目:动态生成表格

循环数组对象

1
2
3
4
5
6
7
8
{
name: 'xx',
sex: 'xx',
}
//用,其中obj[k]获取下表为k的属性值
for(var k in obj){
obj[k];
}
  1. 三种动态创建元素的区别

image-20220723210458794

image-20220723210506321

相当于重新创建并加载一个新的页面,在实际开发中不常用

image-20220723211222777

1
2
3
4
//拼接字符串的效率很低,大约3100毫秒左右
for(var i=0;i<=100;i++){
inner.innerHTML+='<a href=#>xx</a>';
}
1
2
3
4
5
6
//利用数组存取,然后再join,效率很高,大约7毫秒左右
var arr=[];
for(var i=0;i<=100;i++){
arr.push('<a href=#>xx</a>');
}
inner.innerHTML=arr.join('');

image-20220723211233945

1
2
3
4
5
6
//比innerHTML拼接字符串的方法效率高很多,但比innerHTML数组连接相比效率低,大约需要20毫秒左右
var create=document.querySelector('.create');
for(var i=0;i<=100;i++){
var a=document.createElement('a');
create.appendChile(a);
}

面试时可能会问到

DOM重点核心(总结)

image-20220723212238955

image-20220723212323316

image-20220723212405742

image-20220723212421499

image-20220723212434961

image-20220723212525897

image-20220723212728774

image-20220723212900254

image-20220723212934112

DOM事件高级

image-20220723213147868

注册事件(绑定事件)

image-20220724110252698

image-20220724110309160

image-20220724110531411

image-20220724110630107

1
2
3
4
5
6
7
8
9
10
11
// var hello=function(){
// alert('hellonihao ');
// }
function hello(){
alert('hello world');
}
var btns=document.querySelectorAll('button');
btns[1].addEventListener('click',hello);
// btns[1].addEventListener('click',function(){
// alert('hello world');
// })

addEventListener()同一个元素同一个事件可以添加多个监听器(事件处理程序),IE9之前版本支持,推荐使用addEventListener();

image-20220724111826236

attachEvent()是IE9之前版本支持,仅做了解,实际生产环境中不要使用

image-20220724112237837

删除事件(解绑事件)

image-20220724112420776

1
2
3
4
5
6
7
8
9
10
<div>1</div>
<div>2</div>
<div>3</div>
<script>
var divs=document.querySelectorAll('div');
divs[0].onclick=function(){
alert('hello world');
divs[0].onclick=null;//解绑事件
}
</script>

image-20220724114408260

listener不能用匿名函数来写

1
2
3
4
5
6
7
8
9
10
11
12
13
<div>1</div>
<div>2</div>
<div>3</div>
<script>
var divs=document.querySelectorAll('div');
//事件监听
divs[0].addEventListener('click',fun);
//事件监听函数
function fun(){
alert('worji');
divs[0].removeEventListener('click',fun);
}
</script>

image-20220724114854045

第二种使用attachEvent()时的解绑事件函数

DOM事件流

image-20220724120301253

image-20220724120308719

image-20220724165638826

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//结果是:先弹出father,再弹出son
<div class="father">
father
<div class="son">son</div>
</div>
<script>
var father=document.querySelector('.father');
var son=document.querySelector('.son');
father.addEventListener('click',function(){
alert('father');
},true);
son.addEventListener('click',function(){
alert('son');
},true)
</script>

image-20220724170328318

事件对象

1
div.onclick=function(event){}
  1. event就是一个事件对象,写到监听函数里面当做形参来看

  2. 事件对象只有有了事件(onclick onmouseover…)才会存在,他是系统自动创建的,不需要我们传递参数

  3. 事件对象是事件的一系列相关数据的集合,跟事件相关的,比如鼠标点击里面就包含了鼠标的相关信息、鼠标坐标等,如果是键盘事件就包含键盘的信息,不如判断用户按下了那个键等

  4. 事件对象的名称是可以自己修改的,建议使用e来代替

  5. 兼容性问题:IE678用window.event

    1
    2
    3
    div.onclick=function(e){
    console.log(window.event);
    }

    兼容性处理方案:e=e||window.event;但实际开发中不太需要

事件对象的常见属性和方法:

image-20220724182255100

  1. target:

e.target返回的事触发事件的对象(元素),而this返回的事绑定事件的对象,例如当鼠标点击li中的内容1时:

1
2
3
4
5
6
7
8
9
10
11
12
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul=document.querySelector('ul');
ul.addEventListener('click',function(e){
console.log(e.target);
console.log(this);
})
</script>

console.log(e.target)会输出

    ,因为鼠标点击的是li中的1,所以触发元素是li,然后通过冒泡传给ul;console.log(this)会输出ul,因为当前绑定事件的元素是ul

    但e.target存在兼容性问题,在IE678中不能使用,此时需要调用e.srcElement;

    兼容方案:var target=e.target||e.srcElement

    1. currentTarget

      image-20220725125805013

      是跟this非常相似的属性,但currentTarget存在兼容性问题,IE678不认识,所以在实际开发中提倡使用this

    2. e.type返回事件的类型,不带On,如click、mouseover、mouseout

    3. e.preventDefault() 阻止默认的行为(事件)

      例如链接、表单,我们要求当满足某个条件时才可以跳转到该链接上去,没有满足时让链接不跳转,或者让提交按钮不提交

      是一个方法,需要加小括号

    1
    2
    3
    4
    5
    6
    7
    8
    <a href="http://cs.kittates.top">link</a>
    <script>
    var a=document.querySelector('a');
    a.addEventListener('click',function(e){
    e.preventDefault();//dom推荐方法
    e.returnValue;//低版本浏览器使用,IE678
    })
    </script>

    低版本浏览器使用e.returnValue,注意是一个属性,不需要加小括号

    1
    return false

    也能阻止默认行为,没有兼容性问题,但其之后的代码不再执行

    阻止事件冒泡

    面试&&开发

    标准写法:利用e.stopPropagation()方法

    例如让son弹出,而father不弹出,则需要在son中的函数中调用e.stopPropagation()方法来阻止向上一级的冒泡,存在兼容性问题,IE678不能使用

    IE678:window.event.canelBubble=true

    事件委托(代理、委派)

    事件冒泡的一个应用

    image-20220724192947408

    不用为每个子节点绑定事件(太繁琐),不必重复使用DOM

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <ul>
    <li>hello world</li>
    <li>hello world</li>
    <li>hello world</li>
    <li>hello world</li>
    <li>hello world</li>
    </ul>
    <script>
    var ul=document.querySelector('ul');
    ul.addEventListener('click',function(e){
    //e.target表明是哪一个节点,如果是点击的ul中的li,则会显示li,通过e.target.style设置该节点的相应属性即可
    e.target.style.backgroundColor='pink';
    })
    </script>

    常用的鼠标事件

    image-20220724195839866

    常用的鼠标事件:

    1. 禁止鼠标右键菜单

      contextmenu鼠标右键菜单事件

    image-20220724200014206

    虽然不显示右键菜单,但是还是可以通过ctrl+v来复制和粘贴的

    1. 禁止鼠标选中(selectstart 开始选中)

      selectstart鼠标选中事件

    image-20220724200430381

    但是:

    	从文字的最左边还是有一条缝隙是可以复制的
    
    	crtl+A也可以
    
    	F12键调试复制
    

    鼠标事件对象

    image-20220724201045613

    e.screen在实际开发中用的比较少,了解

    小项目:跟随鼠标移动的小天使

    用到的是mousemove事件,获取鼠标移动时的数据

    注意:设置坐标时记得加后面的单位

    1
    2
    img.style.top=y-img.height/2+'px';
    img.style.left=x-img.width/2+'px';

    相同原理的样例:淘宝商品封面放大效果

    常用的键盘事件

    image-20220725130330190

    Alt键、左右箭头键等功能键onkeypress不能识别

    存在执行顺序:

    如果keydown和keypress事件都存在时,先执行keydown,最后执行keyup事件

    image-20220725130953315

    键盘事件对象:

    image-20220725154545871

    通过keyCode可以获取键盘按键的ASCII码值,从而判断按下了哪个键

    **注意:**keyup、keydown事件不区分字母大小写,a和A得到的都是65;keypress是区分大小写的,默认是大写

    小项目1:模拟京东按键输入内容

    小项目2:模拟京东快递单号查询

    拓展开发:射击小游戏

    BOM

    image-20220725162442416

    BOM概述

    image-20220725163132303

    例如在不同的浏览器调用alert函数,弹出的外观是不一样的

    image-20220725163212388

    DOM包含在BOM中,所以

    在学习DOM时,经常是document.querySelector(‘xxx’),而规范的写法是window.document.querySelector(‘xxx’),window可以省略的

    image-20220725163821128

    在DOM中声明的全局变量或方法,在BOM中可以通过window.example的形式调用

    window对象的常见事件

    1. 窗口加载事件

    image-20220725164615657

    image-20220725165004286

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <script>
    window.onload=function(){
    var btn=document.querySelector('button');
    btn.onclick=function(){
    alert('hello');
    }
    }
    </script>
    <button>click</button>

    这样就可以写到文档的任何一个位置了,也可以外部引用

    window.onload若有多个,只会执行最后一个;而window.addEventListener(‘load’,function(){})若有多个时,会全部执行

    DOMContentLoaded:

    image-20220725165236520

    DOMContentLoaded在把基本构架加载完成之后就会执行,而window.onload是将所有内容加载后才执行,相比之下,DOMContentLoaded比window.onload加载速度快

    1. 调整窗口大小事件

      resize事件

      image-20220725190233682

       window.innerWidth 获取当前屏幕的宽度
      

    定时器

    image-20220725190436804

    1. setTimeout()定时器

      image-20220725190557208

      setTimeout()属于window对象,window可以省略,可以直接调用,像alert(); 延时时间是毫秒单位,省略默认为0

      函数调用可以直接在setTimeout()里面写函数,也可以在外部写完后再在setTimeout里面调用,还有一种不提倡的写法:‘函数名()’

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      //方法一
      setTimeout(function(){
      alert('xxx');
      },2000)
      //方法二
      function callback(){
      alert('xxx');
      }
      setTimeout(callback,2000);
      //不提倡写法
      setTimeout('callback()',2000);

      由于页面中可能会有多个不同的定时器,可以给定时器加标识符(名字),例如:

      1
      2
      var time1=setTimeout(callback1,2000);
      var time2=setTimeout(callback2,2000);
       ![image-20220725191625173](image-20220725191625173.png)
      

      小项目:5s之后自动关闭广告

      清除定时器:clearTimeout()

    image-20220725192829342

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <script>
    window.onload=function(){
    var btn=document.querySelector('button');
    var timer=setTimeout(function(){
    console.log('bomb');
    },5000);
    btn.addEventListener('click',function(){
    clearTimeout(timer);
    console.log('stop the bomb');
    });
    }
    </script>
    <button>cancel</button>

    1. setInterval()定时器

    image-20220725193842673

    小项目:倒计时

    清除定时器:clearInterval()

    image-20220725200842171

    小项目:发送短信

    this指向问题

    面试重点

    1. 在全局作用域或者是普通函数中:this指向全局对象window

      **注意:**计时器中的this指向window

    2. 在方法中调用:this指向的是包含该方法的对象(调用者),例如

      1
      2
      3
      4
      5
      var o={
      sayHi: function(){
      console.log(this);//this指向o
      }
      }
    3. 构造函数中调用:this指向构造函数的实例,例如:

      1
      2
      3
      4
      function(){
      console.log(this);//指向fun
      }
      var fun=new fun();

    JS执行队列

    image-20220726114247625

    image-20220726114321302

    例如:

    1
    2
    3
    4
    5
    console.log(1);
    setTimeout(function(){
    console.log(3);
    },1000);
    console.log(2);

    上述结果为:先1 再2 后3,运行了异步处理机制

    JS虽然是单线程的,但是允许处理多个任务

    1
    2
    3
    4
    5
    console.log(1);
    setTimeout(function(){
    console.log(3);
    },0);
    console.log(2)

    上述结果为:先1 再2 后3,原因如下:

    image-20220726115013726

    任务队列又称为消息队列

    JS执行机制

    image-20220726115456875

    执行栈中的任务完成之后,会把任务队列中的任务放到执行栈中,继续执行。所有任务执行完成之后,队列就会清空

    **事件循环(event loop):**执行栈中的同步任务完成之后,会重复的到任务队列中查看是否有新的任务,如果有,就拿到执行栈中执行

    image-20220726120722940

    location对象

    image-20220726122400647

    1. location对象属性

      image-20220726123927115

    重点记住href、search

    小项目1:5秒钟之后自动跳转页面

    小项目2:获取URL参数数据:

    			通过location.search获取参数,格式是类似于?name=kittates的形式,先通过substr获取name=kittates的字串,然后通过split('=')将其分割为数组,得到第二个参数即为所需,
    
    1
    2
    3
    4
    var params=location.search.substr(1);
    var t=params.split('=')[1];
    var span=document.querySelector('span');
    span.innerHTML=t;
    1. location对象的方法

      image-20220726173247251

    location.href()和location.assign()都能够返回前一个页面,location.replace()不能后退,replace将url的地址替换了,以前地址的缓存被替换了

    image-20220726173733907

    image-20220727131042304

    根据是手机端还是电脑端打开的页面从而以不同的形式展现

    image-20220727131445634

    了解即可,一般情况下都是服务端做的

    history对象

    image-20220727131807080

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <script>
    var btn=document.querySelector('button');
    btn.addEventListener('click',function(){
    history.forward();//前进
    history.back();//后退
    history.go(2);//前进2步
    history.go(-3);//后退3步
    })
    </script>

    一般在浏览器中不会使用,但是会在一些OA办公系统中见到

    PC端网页特效

    image-20220727133149802

    元素偏移量offset

    image-20220727135803280

    offsetTop和offsetLeft以带有定位的父亲为准,如果有父亲或者父亲没有定位,则以body为准

    offset与style的区别

    image-20220727141445529

    行内样式表:

    1
    <div style=''>

    小项目1:获取鼠标在盒子内的坐标

    小项目2:拖动模态框

    小项目3:仿京东放大镜页面效果

    元素可视区client

    image-20220727205910268

    与offset的区别是:clientWidth、clientHeight不包含边框

    淘宝flexible.js源码分析

    1. 立即执行函数:不需要调用,立马能够自己执行的函数

      写法1:(function() {})()

      1
      2
      3
      (function(){
      console.log(2);
      })()

      写法2:(function(){}())

      1
      2
      3
      (function(){
      console.log(2);
      }())

      里面也可以传递参数

      1
      2
      3
      (function(a,b){
      console.log(a,b);
      })()

      也可以为立即函数起个名字

      1
      2
      3
      (function sum(a,b){
      console.log(a+b);
      })(a,b)

      立即函数独立的创建了一个作用域,里面所有的变量都是局部变量,不会有命名冲突的情况

       ![image-20220729112920811](image-20220729112920811.png)
      

    image-20220803092246234

    元素滚动scroll

    image-20220729113254601

    scrollWidth和scrollHeight不包含边框,但是包含padding,内容可能会超出盒子的范围,所以获取的是元素实际的大小

    1
    2
    //显示滚动条
    overflow: auto

    scroll事件

    小项目:仿淘宝固定右侧侧边栏

    注意

    获取页面被卷去的高度:window.pageYOffset,但存在兼容性问题

    image-20220729121130865

    DTD:

    兼容性封装函数如上

    image-20220729121405687

    image-20220729121501468

    页面滚动距离用window.pageXOffset、window.pageYOffset获取

    mouseenter和mouseover的区别:

    image-20220729161710530

    mouseover子盒子会冒泡到当前盒子而mouseenter不会

    image-20220803095029188

    mouseover会冒泡

    动画函数封装

    image-20220729161936559

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    <style>
    div {
    position: absolute;
    left: 0;
    width: 100px;
    height: 100px;
    background-color: pink;
    }

    span {
    position: absolute;
    left: 0;
    top: 200px;
    display: block;
    width: 150px;
    height: 150px;
    background-color: purple;
    }
    </style>
    <div></div>
    <span>夏雨荷</span>
    <script>
    // 简单动画函数封装obj目标对象 target 目标位置
    function animate(obj, target) {
    var timer = setInterval(function() {
    if (obj.offsetLeft >= target) {
    // 停止动画 本质是停止定时器
    clearInterval(timer);
    }
    obj.style.left = obj.offsetLeft + 1 + 'px';
    }, 30);
    }
    var div = document.querySelector('div');
    var span = document.querySelector('span');
    // 调用函数
    animate(div, 300);
    animate(span, 200);
    </script>

    上述存在使用absolute relative动画速度不同的问题?

    解决:

    absolute:如果元素没有已定位的祖先元素,那么它的位置则是相对于最初的包含块(body)。

    relative:元素“相对于”它的原始起点(上一个位置)进行移动

    封装

    image-20220803101200997

    上述方法每次调用就会开辟一段空间,性能不太好。

    性能优化+消除变量歧义:

    image-20220803105336298

    将timer作为调用对象的属性进行操作

    给动画设置按钮,点击按钮执行,出现问题:

    按钮点击次数越多,动画速度越快,解决方案:

    先清除之前的定时器,再调用动画

    image-20220803110246053

    缓动动画

    image-20220803111019357

    代码实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <script>
    function animate(obj,target){
    obj.timer=setInterval(function(){
    if(obj.offsetLeft==target){
    clearInterval(obj.timer);
    }
    //再计时器内部设置步长,将步长设置为整数,避免出现精度问题而无法正常到达目标位置
    var step=Math.ceil((target-obj.offsetLeft)/10);
    // if(step<1) clearInterval(obj.timer);
    obj.style.left=obj.offsetLeft+step+'px';
    console.log("lasting");
    },15)
    }
    var div=document.querySelector('div');
    animate(div,700)
    </script>

    实现后退(比如点击500到达500位置,点击800到达800位置,实现前进后退功能):

    step<0要向下取整,要加判断

    1
    step = step<0?Math.floor(step):Math.ceil(step)

    动画函数添加回调函数

    将函数名作为参数传递过去

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <script>
    function animate(obj,target,callback){
    obj.timer=setInterval(function(){
    if(obj.offsetLeft==target){
    clearInterval(obj.timer);
    //定时器结束后执行callback函数
    if(callback){
    callback();
    }
    }
    //再计时器内部设置步长,将步长设置为整数,避免出现精度问题而无法正常到达目标位置
    var step=Math.ceil((target-obj.offsetLeft)/10);
    // if(step<1) clearInterval(obj.timer);
    obj.style.left=obj.offsetLeft+step+'px';
    // console.log("lasting");
    },15);

    }
    var div=document.querySelector('div');
    animate(div,700,function(){console.log("hello");})
    </script>

    动画函数单独封装成一个js文件

    小项目:引用animate动画函数

    通过一下方式引用

    1
    <script src="animate.js"></script>

    出现的问题:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function animate(obj,target,callback){

    clearInterval(obj.timer);
    obj.timer=setInterval(function(){

    console.log(obj.offsetLeft);
    var step=(target-obj.offsetLeft)/10;
    step = step<0?Math.floor(step):Math.ceil(step)
    if(obj.offsetLeft==target){
    clearInterval(obj.timer);
    //定时器结束后执行callback函数
    callback&&callback();
    }
    //再计时器内部设置步长,将步长设置为整数,避免出现精度问题而无法正常到达目标位置
    obj.style.left=obj.offsetLeft+step+'px';
    },15);
    }

    中间的

    1
    if(obj.offsetLeft==target)()

    最好使用==,因为存在如果target是负值-160的时候,而此时是>=,(target-obj.offsetLeft)/10=(-160-0)/10=-16,这是会发现-16是>=target,也就是-16>=-160的,所以执行一次就clear了,所以综上,还是使用==

    1
    2
    var step=(target-obj.offsetLeft)/10;
    step = step<0?Math.floor(step):Math.ceil(step)

    第一行先保持原样,第二行在据实际判断执行的操作

    小项目1:网页轮播图,在品优购上面操作

    手动调用事件,例如:

    arrow_r.click():模拟手动点击触发事件

    节流阀

    image-20220803202030268

    小项目2:返回顶部

    window.scrollTo(x,y)

    滚动到文档中的某个坐标。

    image-20220804134743887

    1
    2
    3
    4
    window.scrollTo({
    top: 1000,
    behavior: "smooth"
    });

    小项目3:筋斗云

    移动端网页特效