JavaScript DOM/BOM操作笔记总结

之前学习的JS的笔记现在整理发布到到博客,也当是复习知识

什么是DOM?

什么是DOM?

文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口
W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式。

操作元素

JavaScript的DOM操作可以改变网页内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等。注意以下都是属性

改变元素内容

1
2
3
4
5
element.innerText
从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉

element.innerHTML
起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行

获取元素

getElementById……略

通过HTML5新增的方法获取

1
2
3
1.document.getElementeByclasaName('类名');//根据类名返回元素对象集合
2.document.querySelector('选择器'); //根据指定选择器返回第一个元素象
3.document.querySelectorA11('选择器'); //根据指定选择器返回

表单元素操作

利用DOM可以操作如下表单元素的属性:

1
type、value、checked、selected、disabled

样式属性操作

1
2
3
4
5
6
7
8
9
10
11
我们可以通过JS修改元素的大小、颜色、位置等样式。

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

// 在单个语句中设置多个样式
elt.style.cssText = "color: blue; border: 1px solid black";
// 或者
elt.setAttribute("style", "color:red; border: 1px solid blue;");
// 设置特定样式,同时保持其他内联样式值不变
elt.style.color = "blue";

注意:
1.Js里面的样式采取驼峰命名法比如 fontsize、backgroundcolor e
2.Js修改sty1e样式操作,产生的是行内样式,css权重比较高

3.如果样式修改较多,可以采取操作类名方式更改元素样式。
4.clasa因为是个保留字,因此使用className来操作元素类名属性
5.className 会直接更改元素的类名,会覆盖原先的类名。

案例:循环精灵图

案例:显示隐藏文本框内容

案例:判断输入是否符合条件

image-20200305150450394

排他思想

image-20200305150534282

如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法:
1.所有元素全部清除样式(干掉其他人)
2.给当前元素设百样式(留下我自己)
3.注意顺序不能颠倒,首先干掉其他人,再设置自己

代码:略

案例:image-20200305150602322

image-20200305150609746

自定义属性的操作

1.获取属性值

element.属性 获取属性值。
element.getAttribute(’属性);

区别

element.属性 获取内置属性值(元素本身自带的属性)
element.getAttribute(属性);主要获得自定义的属性(标准)我们程序员自定义的属性

自定义属性值的操作

1
2
element.属性='值'	//设置内置属性值。
element.setattribute('属性','值');

自定义属性

自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
自定义属性获取是通过getAttribute(’属性’)获取。
但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。
H5给我们新增了自定义属性:

设置H5自定义属性:

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

1
2
3
4
5
6
比如<div data-index=“1"></div>
或者使用JS设置
element.setAtribute('data-index',2)

//如果自定义属性里面有多个.链接的单词,我们获取的时候采取驼峰命名法
//h5新增的获取自定义属性的方法它只能获取data-开头的

节点操作

为什么需要节点操作

image-20200305151706763

节点概述

image-20200305151756506

一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
·元素节点nodeType为1

·属性节点nodeType为2
·文本节点nodeType为3(文本节点包含文字、空格、换行等)

在实际开发中,节点操作主要操作的是元素节点

节点层级

父节点

1
node.parentNode

子节点

1
2
3
4
parentNode.firstChild 
firstChild返回第一个子节点,找不到则返回null。同样,也是包含所有的节点。
parentNode.lastChild
lastChild返回最后一个子书点,找不到则返回null。同样,也是包含所有的节点。

firstChild第一个子节点不管是文本节点还是元素节点

1
2
3
4
5
6
7
parentNode.firstElementChild 
firstE1ementChi1d 返回第一个子元素节点,找不到则返回null

parentNode.lastElementChi1d
1astE1ementChild返回最后一个子元素节点,找不到则返回null

注意:这两个方法有兼容性问题,TE9以上才支持。

注意元素节点和节点的区别

实际开发中,firstchild和1astchild包含其他节点,操作不方便,而firstElementchild和1astE1ementchi1d又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?

dm

兄弟节点

1
2
3
4
5
6
1.node.nextsib1ing 
nextSib1ing返回当前元素的下一个兄弟节点,找不到则返回nu11。同样,也是包含所有的节点。

2.node.previouasibling
previousSibling 返回当前元素上一个兄弟节点,找不到则返回nu11。同样,也是包含所有的节点。

1
2
3
4
5
6
7
3.node.nextElementsibling 
nextE1ementsibling返回当前元素下一个兄弟元素节点,找不到则返回null

4.node.previousElementsibling
previousE1ementsibling返回当前元素上一个兄弟节点,找不到则返回null

注意:这两个方法有兼容性问题,IE9以上才支持。

如何解决兼容性问题?

封装一个兼容性的函数

image-20200305152905858

创建节点

1
2
3
document.createElement('tagName')

创建由tagName指定的HTML元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。

添加节点

1
2
node.appenchild(chile)	//添加到末尾
node.insertBefore(chile,指定元素) //添加到指定节点的前面

案例:简单版发布留言案例

节点删除

1
2
node.removeChild(child)
//node.removeChild()发放从DOM中删除一个子节点,返回删除的节点.

案例:添加删除按钮

复制节点(克隆节点)

1
2
node.cloneNode()
//方法返回调用该方法的节点的一个副本。也称为克降节点/拷贝节点

注意:
1.如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子
2.如果括号参数为true,则是深应拷贝,会复制节点本身以及里面所有的子节点。

三种动态创建元素的区别

document.write()

element.innerHTL()
document.createElement()

区别
1.document.write 是直接将内容写入页面的内容流,但是文流执行完毕,则它会导致页面全部重绘
2.innerHTL是将内容写入某个Dox节点,不会导致页面全部重绘

3.innerHTML创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
4.createElement()创建多个元素效率稍低一点点,但是结构更清晰

不同浏览器下,innerHTML 效率要比 createElement 高

DOM重点核心

增删改查 属性操作,事件操作

创建

1.document.write
2.innerHTML
3.createElement

1.appendChild

2.insertBefore

1.removeChild

主要修改dom的元素属性,dom元素的内容、属性,表单的值等
1.修改元素属性:src、href、title等

2.修改普通元素内容:innerHTML、innerText
3.修改表单元素:value、type、disabled等
4.修改元素样式:style、className

主要针对于自定义属性。
1.setAttribute:设置dom的属性值
2.removeAttribute :移除属性

事件操作

给元素注册事件,采取 : 事件源.事件类型=事件处理程序

onclick 鼠标点击左键触发

onmouseover 鼠标经过触发

onmouseout 鼠标离开触发

onfocus 获得鼠标焦点触发

onblur 失去鼠标焦点触发

onmousemove 鼠标移动触发

onmouseup 鼠标标单起触发

onmousedown 鼠标按下触发

注册事件(事件绑定)

给元素添加事件,称为注册事件或者绑定事件。
注册事件有两种方式:传统方式和方法监听注册方式

image-20200307144712704

传统方法(略)

attachEvent 事件监听

1
eventTarget.attachEvent(eventNamewithon,callback)

eventrarget.attachEvent()方法将指定的监听器注册到eventrarget(目标对象)上,当该对象触发指定的事件时,指定的回调函数就会被执行。

该方法接收两个参数:
eventNameWithOn:事件类型字符串,比如onclick、onmouseover,这里要带on
callback: 事件处理函数,当目标触发事件时回调函数被调用

计算机生成了可选文字: divs[1].addEventListener(/images/JavaScript%E5%85%A5%E9%97%A8%E7%AC%94%E8%AE%B0%E6%80%BB%E7%BB%93/clip_image001-1583564072529.png)

注册事件兼容性解决方案

image-20200307145054161

兼容性处理的原则:首先照顾大多数浏览器,再处理特殊浏览器

事件删除(解绑事件)

删除事件的方式

1.传统方式

eventTarget.onclick = null;

2.方法监听注册方式

eventTarget.removeEventListener(type,listener[,usecapture]);

DOM事件流

事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。
比如我们给一个div注册了点击事件:

image-20200307145540000

1.事件冒泡:IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到DOM最顶层节点的过程。
2.事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。

我们向水里面扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点(最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡。实际开发注重冒泡

image-20200307145703762

事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。
注意
1.Js代码中只能执行捕获或者冒泡其中的一个阶段。
2.onclick和attachEvent 只能得到冒泡阶段。
3.addEventListener(type,listenert,usecapture])第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
4.实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
5.有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
6.事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件。

事件对象

什么是事件对象

1
2
3
eventrarget.onclick=function(eventy){}
eventTarget.addEventListener('click'function(event){})
//这个event 就是事件对象,我们还喜欢的写成e或者evt

官方解释:event对象代表事件的状态,比如键盘按键的状态鼠标的位置、鼠标按钮的状态。

简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,它有很多属性和方法。

这个event是个形参,系统帮我们设定为事件对象,不需要传递实参过去。
当我们注册事件时,event对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)。

事件对象的兼容性方案

事件对象本身的获取存在兼容问题:
1.标准浏览器中是浏览器给方法传递的参数,只需要定义形参e就可以获取到。
2.在IE6~8中,浏览器不会给方法传递参数,如果需要的话,需要到window.event中获取查找。
解决:

1
e=ell window.event;

阻止事件冒泡

阻止事件冒泡的两种方法

事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到到DOM最顶层节点。
事件省泡本身的特性,会带来的坏处,也会带来的好处,需要我们灵活掌握。

1
2
3
4
//标准写法:利用事件对象里面的stoppropagation()方法
e.stopPropagation()

//非标准写法:IE6-8利用事件对象cancelBubble属性

阻止事件冒泡的兼容性解决方案

1
2
3
4
5
if(e && e.stopPropagation){
e. stopPropagation();
} else{
window.event.cancelBubble=true;
}

事件对象

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

image-20200307150845708

事件委托

事件委托
事件委托也称为事件代理,在jQuery里面称为事件委派。
事件委托的原理
不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用管泡原理影响设置每个子节点。
案例:给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,因为点击li,事件会智泡到ul上,ul有注册事件,就会触发事件监听器。
事件委托的作用
我们只操作了一次DOM,提高了程序的性能。

常用的鼠标事件

1.禁止鼠标右键菜单
contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单

1
2
3
document.addEventListener('contextmenu'function(e){
e.preventDefault();
})

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

1
2
3
document.addEventListener('selectstart'function(e){
e.preventDefault();
})
1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
我是一段不愿意分享的文字
<script>
//1.contextmenu我们可以禁用右键菜单
document.addEventListener('contextmenu'function(e){
e.preventDefault();
})
//2.禁止选中文字selectstart
document.addEventListener('selectstart'function(e){
e.preventDefault();
})
</script>
</body>

常用鼠标事件

event对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段我们主要是用鼠标事件对象MouseEvent 和键盘事件对象 KeyboardEvent。

image-20200307151650282

image-20200307151715792

案例:跟随鼠标的天使

常用键盘事件

image-20200307151828846

注意:
1.如果使用addEventuistener不需要加on
2.onkeypress和前面2个的区别是,它不识别功能键,比如左右箭头,shift等。
3.三个事件的执行顺序是:keydown–keypress—keyup

键盘事件对象

image-20200307152000430

注意:onkeydown和onkeyup不区分字母大小写,onkeypress区分字母大小写。
在我们实际开发中,我们更多的使用keydown和keyup,它能识别所有的键(包括功能键)Keypress不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCll值

案例:模拟京东按键输入内容 按下s键,光标定位到搜索框

案例:模拟京东快递单查询 输入内容时,文本框上面自动显示大号字的内容

image-20200307152232527

BOM概述

BOM的构成

window对象是浏览器的顶级对象,它具有双重角色。
1.它是Js访问浏览器窗口的一个接口。
2.它是一个全局对象。定义在全局作用域中的变量、函数都会变成window对象的属性和方法。
在调用的时候可以省略window,前面学习的对话框都属于window对象方法,如alert()、prompt()等。
注意:window下的一个特殊属性window.name

window对象的常见事件

窗口加载事件

1
2
3
window.onload=function(){}
或者
window.addEventListener("load"function(){});

1.有了window.onload就可以把JS代码写到页面元素的上方,因为onload是等页面内容全部加载完再去执行处理函数。
2.window.onload传统注册事件方式只能写一次,如果有多个,会以最后一个window.onload为准。

1
document.addEventListener('DOMContentLoaded',function(){})

DOMContentloaded 事件触发时,仅当DOMm载完成,不包括样式表,图片,flash等等。
le9以上才支持
如果页面的图片很多的话,从用户访问到onload触发可能需要较长的时间交互效果就不能实现,必然影响户的体验,此时用DOMContentloaded事件比较合适。

调整窗口大小事件

1
2
window.onresize=function(){}
window.addEventListener("resize",function(){});

window.onresize是调整窗口大小加载事件,当触发时就调用的处理函数。

定时器

setTimeout()定时器

1
window.setTimeout(调用函数,[延迟的毫秒数]);

setTimeout()方法用于设置一个定时器,该定时器在定时器到期后执行调用函数。
注意:
1.window可以省略。
2.这个调用函数可以 直接写函数,或者 写函数名 或者采取字符’串函数名()’三种形式。第三种不推荐
3.延迟的毫秒数省略默认是0,如果写,必须是毫秒。
4.因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。

setTimeout()这个调用函数我们也称为 回调函数calback
普通函数是按照代码顺序直接调用。
而这个函数,需要等待时间,时间到了才去调用这个函数,因此称为回调函数。简单理解:回调,就是回头调用的意思。上一件事干完,再回头再调用这个函数。
以前我们讲的element.onclick=function(){}或者element.addEventtistener(“cick”,fm);里面的函数也是回调函数。

案例:5秒后自动关闭的广告

clearTimeout()方法取消了先前通过调用setrimeout()建立的定时器。
注意:
1.window可以省略。

setinterval定时器

1
window.setInterval(回调函数,[间隔的毫秒数]);

setlnterval()方法重复调用一个函数,每隔这个时间,就去调用一次回调函数。
注意:
1.window可以省略。
2.这个调用函数可以直接写函数,或者写函数名或者采取字符串’函数名()’三种形式。
3.间隔的毫秒数省略默认是0,如果写,必须是毫秒,表示每隔多少毫秒就自动调用这个函数。
4.因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。

案例:倒计时

cleanrInterval()方法取消先前通过调用setInterval()建立的定时器

案例:发送短信 60秒之内不能再次点击,防止重复发送

this

this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定his到底指向谁,一般情况下this的最终指向的是那个调用它的对象
全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)

JS执行机制

同步和异步

为了解决这个问题,利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程。于是,JS中出现了同步和异步。
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。
异步
你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。

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

同步任务
同步任务都在主线程上执行,形成一个执行栈。
异步任务
JS的异步是通过回调函数实现的。一般而言,异步任务有以下三种类型

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

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

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

异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)。

image-20200307154641274

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

image-20200307154733165

image-20200307154758084

location对象

lovation对象的属性

image-20200307155153056

重点记住:href 和 search

案例:5秒之后自动跳转页面

案例:获取URL参数数据

image-20200307155403870

lovation对象的方法

image-20200307155433000

navigator

navigator对象包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值。
下面前端代码可以判断用户那个终端打开页面,实现跳转

image-20200307155557394

history对象

window对象给我们提供了一个history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。

image-20200307155727978

网页特效↓

元素偏移量 offset系列

概述

offset 翻译过来就是偏移量,我们使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等。
获得元素距离带有定位父元素的位置
获得元素自身的大小(宽度高度)

注意:返回的数值都不带单位
ofset系列常用属性:

image-20200307155937841

offset与style的区别

image-20200307160010928

案例:获取鼠标在盒子的坐标

案例:模态框拖拽

案例:淘宝图片放大镜

image-20200307160135031

元素可视区 client系列

client 翻译过来就是客户端,我们使用client系列的相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以动态的得到该元素的边框大小、元素大小等。

image-20200307160241702

案例:淘宝flexible.js源码分析

立即执行函数(function(){})() 主要作用:创建一个独立的作用域

元素滚动sroll系列

scroll 翻译过来就是滚动的,我们使用scroll系列的相关属性可以动态的得到该元素的大小、滚动距离等。

image-20200307160445908

案例:仿淘宝固定右侧边栏

三大系列总结

image-20200307160524222

他们主要用法:
1.offset系列经常用于获得元素位置 offsetLeft offsetTop
2.client经常用于获取元素大小clientWidth clientHeight
3.scroll经常用于获取滚动距离 scrollTop scrolleft
4.注意页面滚动的距离通过window.pagexoffset获得

动画函数封装

缓动效果原理

缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来思路:
1.让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
2.核心算法:(目标值-现在的位置)/10做为每次移动的距离步长
3.停止的条件是:让当前盒子位置等于目标位置就停止定时器

演示:

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//ydjl:移动到指定位置  (obj.offsetLeft)
function animate(obj,ydpx) {
//清除定时器 防止每一次调用都产生一个定时器,叠加导致问题(速度变快)
clearInterval(obj.timer);
obj.timer=setInterval(function () {
var step = (ydpx - obj.offsetLeft) / 10; //移动距离
//取整
step = step>0 ? Math.ceil(step) : Math.floor(step);
//判断是否移动到指定位置
if(obj.offsetLeft == ydpx)
{
//清除定时器,停止移动
clearInterval(obj.timer);
}
//修改left实现移动
obj.style.left = obj.offsetLeft + step + 'px';

},15)//移动间隔设置
}


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.boks{
position: absolute;
top: 300px;
left:0;
width: 100px;
height: 100px;
background-color: #ff0011;
}
</style>

</head>
<body>
<button class="yd500">移动500px</button>
<button class="yd800">移动800px</button>
<div class="boks">hezi</div>
</body>
<script>
function animate(obj,ydpx) {
//清除定时器
clearInterval(obj.timer);
obj.timer=setInterval(function () {
var step = (ydpx - obj.offsetLeft) / 10;
step = step>0 ? Math.ceil(step) : Math.floor(step);
if(obj.offsetLeft == ydpx)
{
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + step + 'px';

},15);
}
var yd500 = document.querySelector(".yd500");
var yd800 = document.querySelector(".yd800");
//盒子
var boks = document.querySelector(".boks");

yd500.addEventListener('click', function() {
// 调用函数
animate(boks, 500); //传递要移动的对象 和 移动位置
})

yd800.addEventListener('click', function() {
// 调用函数
animate(boks, 800); //传递要移动的对象 和 移动位置
})
</script>
</html>

案例:轮播图

节流阀

&& 运算符的运用

mouseenter 和mouseover的区别

mouseenter 鼠标事件
当鼠标移动到元素上时就会触发mouseenter事件
类似mouseover,它们两者之间的差别是
mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter只会
之所以这样,就是因为mouseenter不会冒泡
跟mouseenter搭配鼠标离开 mouseleave同样不会冒泡

window.sessionStorage

image-20200307161431078

window.localStorage

image-20200307161453888

触屏事件(略)

剩下的为一些特效实现(略~