目录
1 Web API
2 DOM
2.1 DOM(文档对象模型) 简介
2.2 获取元素
2.3 事件基础
2.4 操作元素
2.5 节点操作
2.6 事件操作
3 事件高级
3.1 注册事件
3.2 删除事件(解绑事件)
3.3 DOM 事件流
3.4 事件对象
3.5 事件委托(代理、委派)
3.6 常用的鼠标事件
3.7 鼠标事件对象 MouseEvent
3.8 常用的键盘事件
3.9 键盘事件对象 keyboardevent
4 BOM
4.1 BOM的构成
4.2 window 对象的常见事件
4.3 this 指向问题
4.4 JS执行机制
4.5 location 对象
4.6 navigator 对象
4.7 history 对象
1 Web API
- API(应用程序编程接口):预先定义的函数。给程序媛提供工具,能够更轻松地实现想完成的功能。
- Web API:浏览器提供的一些浏览器功能和页面元素的API(BOM和DOM)。例如:alert
2 DOM
主要包括创建、增删改查、事件操作
2.1 DOM(文档对象模型) 简介
文档对象模型(DOM)是W3C组织推荐的处理HTML语言的标准编程接口。通过DOM接口可以改变网页的内容、结构和样式。
2.1.2 DOM树
- 文档:每个页面都是文档,DOM中用document 表示
- 元素:页面中所有标签都是元素,DOM中用element表示
- 节点:网页中所有的内容都是节点(标签、属性、文本、注释等),DOM中用node表示。
DOM 把以上内容都看作是对象,所以称为文档对象模型。
2.2 获取元素
2.2.1 通过 ID 获取
使用 getElementById('id名') 获取元素。
- 因为文档页面从上往下加载,先得有标签,script才能获取,所以script写在标签下面
- 函数的参数是大小写敏感的字符串;
- 返回id匹配的元素对象;若没有该对象,返回null;
- 可以通过 console.dir(元素对象) 打印元素对象,查看对象里面的属性和方法。
2.2.2 通过标签名获取
使用 getElementsByTagName('标签名') 方法返回带有指定标签名的集合
- 返回的是获取到的指定标签名的集合,以伪数组的形式存储
- 得到的元素是随着标签内容,动态变化的
- 若页面中只有一个标签,还是返回伪数组的形式
- 若页面中没有指定的标签,返回一个空的伪数组
- 可以获取指定某个父元素内部所有的指定标签名
// 通过标签名先获取父元素对象,然后获取子元素对象
var ol = document.getElementsByTagName('ol');
var li = ol[o].getElementsByTagName('li');
// 因为getElementsByTagName返回的是一个数组,还要指定索引号来得到某个对象,略繁琐
// 一般开发中,会先用getElementById()获取父元素对象
var ol = document.getElementById('ol');
var li = ol.getElementsByTagName('li');
2.2.3 通过 HTML5新增的方法
- getElementsByClassName('类名')
- 根据类名返回元素对象的集合
- 这里的类名是不需要加符号的,直接写类名即可,如:'box'
- querySelector('选择器')
- 根据指定选择器返回第一个元素对象
- 因为选择器不确定是类选择器还是id选择器,所以选择器要加符号,如:'.box','#id5','li'
- querySelectorAll('选择器')
- 根据指定选择器返回所有元素对象
- 还是以伪数组的形式
2.2.4 获取特殊元素
- 获取 body 元素:document.body
- 获取 html 元素:document.documentElement
2.3 事件基础
事件就是触发--响应机制。事件由三部分组成:事件源、事件类型、事件处理程序。
- 事件源:事件被触发的对象
- 事件类型:如何触发?什么事件?比如鼠标点击
- 事件处理程序:通过一个函数赋值的方式完成。
2.4 操作元素
2.4.1 改变元素内容
- element.innerText:从起始位置到终止位置的内容,不识别 html 标签,同时空格、换行也会去掉
- element.innerHTML:从起始位置到终止位置的内容,识别 html 标签,同时保留空格和换行。一般用这个。
- 这两个属性是可读写的,可以获取元素里面的内容。如:标签.innerText,标签.innerHTML 。
- innerText不识别 html 标签,innerHTML 识别 html 标签。
2.4.2 改变元素属性内容
可以使用this,this指向事件函数的调用者。
- 常用的元素属性有:innerText、innerHTML、src、href、id、alt、title
- 表单属性操作
- value:改变表单里面的内容。用 innerHTML 是没有效果的。
- disabled:表单被禁用,点击后被禁用。disabled = true
- type:改变表单的类型。应用:点击按钮,显示密码
- onfocus:获得焦点
- onblur:失去焦点
- 样式属性操作:元素的大小、颜色、位置等
- element.style:行内样式操作。如:div.style.backgroundColor
- JS 里面的样式采用驼峰命名法,如:fontSize、backgroundColor;
- JS 修改样式后,产生的是行内样式,CSS 权重比较高;
- 若样式比较少,功能简单的情况下使用。
- element.className:类名样式操作
- 修改当前元素的类名,例如:this.className = 'change';
- 注意,类名不需要加点。
- 适合样式较多,功能复杂的情况。
- 设置后,会覆盖掉原先的类名。
- 如果想保留原先的类名,可以像CSS一样用空格分隔。如:this.className = '原来的类名 修改的类名'。
2.4.3 排他思想
如果又同一组元素,想要某一个元素的样式改变,先把其他元素的样式去掉,再设置某一个元素的样式。这样的想法称为排他思想。
2.4.4 自定义属性的操作
元素属性可以自定义。获取属性值的方法:
- element.属性:获取元素本身自带的属性,如id、class等。
- getAttribute('属性'):获取元素自定义的属性,也可以获取内置属性。
设置元素属性值
- element.属性 = '值':更改元素内置属性。
- element.setAttribute('属性','值'):主要针对自定义属性,也可以更改内置属性。
- 属性中class比较特殊,应该写className,就可以更改class的值
移除属性
- element.removeAttribute('属性'):移除元素的某个属性
2.4.5 H5 自定义属性
自定义属性的目的是为了保存并使用数据,有些数据可以保存到页面中。为了区分内置属性和自定义属性,H5规定自定义属性以 ‘data-’ 开头作为属性名,并赋值。
- .setAttribute('自定义属性名',属性值):通过JS设置自定义属性的值。
- .getAttribute('data-自定义属性名'):获取自定义属性的值,更常用。
- element.dataset.属性名或者element.dataset['自定义属性名']
- H5新增的方法,ie11才开始支持。
- dataset是一个存放了所有以data开头的自定义属性的对象。
- 若自定义属性名里有多个 - 链接的单词,获取时,用驼峰命名法。
- 如 data-list-name = 'andy',获取时,应该是 element.dataset.listName 或者element.dataset['listName']。
- dataset方法无法获得没有以data开头的自定义属性。
2.5 节点操作
获取元素之前都是使用DOM提供的方式,除此之外还可以使用父子级关系获取,也就是节点操作
- 文档中所有的内容都可以称为节点,包括:文档节点、文本节点、元素节点、属性节点等。
- 节点至少拥有nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值)三个基本属性
- 元素节点 nodeType为1。开发中,主要操作的是元素节点。
- 属性节点 nodeType为2。
- 文本节点 nodeType 为3,文本节点包括文字、空格、换行等。
2.5.1 节点层级
父子层级
- node.parentNode:得到的是离元素最近的父级节点。找不到父节点返回null。
- parentNode.childNodes:得到父节点的所有的子节点,包含元素节点、文本节点(换行)等。
- 通过元素节点类型来判断获得的节点是否为元素节点。
- 元素节点类型为1,属性节点类型为2,文本节点类型为3。
- parentNode.children:获取所有的子元素节点,返回一个伪数组。实际开发常用的方法。
- parentNode.children[0]:获取第一个子元素节点
- parentNode.children[parentNode.children.length - 1]:获取最后一个子节点
- parentNode.firstChild:获取第一个子节点,不管是文本节点还是元素节点
- parentNode.lastChild:获取最后一个子节点,不区分文本还是元素
- parentNode.firstElementChild:获取第一个子元素节点,找不到返回null
- parentNode.lastElementChild:获取最后一个子元素节点,找不到返回null
- firstElementChild和lastElementChild有兼容性限制,ie9以上才支持
兄弟层级
- node.nextSibling:返回当前元素的下一个兄弟节点,找不到返回null,包含文本节点
- node.previousSibling:返回当前元素的上一个兄弟节点,找不到返回null,包含文本节点
- node.nextElementSibling:返回当前元素的下一个兄弟元素节点
- node.previousElementSibling:返回当前元素的上一个兄弟元素节点
- nextElementSibling和previousElementSibling有兼容性限制,ie9以上才支持
- 为了解决兼容性问题,可以自己封装一个兼容性函数
-
function getNextElementSibling(element){
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1){
return el;
}
}
return null;
}
2.5.2 创建节点
- document.creatElement('tagName'):创建节点
2.5.3 添加节点
添加节点分为两步:1)创建元素;2)添加元素。
- node.appendChild(child):其中node 是父级,child是子级。
- 参数不用带引号
- 新添加的节点,会放在父元素的最后面,类似于数组中的push
- 例如:ul.appendChild(li);
- node.insertBefore(child, 指定元素)
- 将节点插入到指定元素的前面
- 例如:ul.insertBefore(li,ul.children[0]) ,插入到第一个元素的前面
2.5.4 删除节点
- node.removeChild(child):删除一个子节点,返回删除的节点
- node是父节点,child是孩子节点
- 应用:留言板删除
- 注册事件用小点,不用冒号!
- textarea的值是value,不是innerHTML;
- 如果不想让a 链接跳转,可以给href上写javascript: ;
2.5.5 复制节点
- node.cloneNode():将节点Node复制一份
- 和创建节点一样,需要先复制,再添加到父节点中,才会显示出来
- 若参数为空或false,表示浅拷贝,只复制节点标签,不复制内容
- 若参数为true为深拷贝,复制节点标签及里面的内容。深拷贝的标签和原标签一起改变
2.5.6 三种动态创建元素区别 (了解)
- document.write()
-
document.write(123
);
- 如果页面文档流加档完毕,再调用这句话,会导致页面重绘。重新产生一个页面。
- element.innerHTML
- innerHTML创建多个元素的效率更高(不要拼接字符串,要采取数组形式拼接),结构稍微复杂
- 创建完毕,页面不会重绘
- document.createElement()
- 这两者执行上,没什么大的区别;他俩的区别可能会在面试的时候碰到!
- creatElemen()的执行效率稍微低,但是结构更清晰
- 创建完毕,页面不会重绘
2.6 事件操作
给元素注册事件,采用 事件源.事件类型 = 事件处理程序 的方式
- onclick:鼠标点击左键触发
- onmouseover:鼠标经过触发
- mouseover经过自身盒子触发,经过子盒子也会触发,因为子盒子会冒泡给父盒子,触发父盒子的事件
- onmouseenter:鼠标经过触发
- mouseenter只经过自身盒子触发,经过子盒子不会触发,因为mouseenter没有冒泡
- 跟mouseenter搭配鼠标离开的是mouseleave,同样不会冒泡
- onmouseout:鼠标离开触发
- onfocus:获得鼠标焦点触发
- onblur:失去鼠标焦点触发
- onmousemove:鼠标移动触发
- onmouseup:鼠标弹起触发
- onmousedown:鼠标按下触发
- contextmenu:控制显示上下文菜单,也就是右键菜单,主要用于程序媛取消默认的上下文菜单
-
document.addEventListener('contextmenu', function(e){
// 禁止显示右键菜单
e.preventDefault();
})
- selectstart:开始选中,一般用于禁止鼠标选中
-
document.addEventListener('selectstart', function(e){
e.preventDefault();
})
3 事件高级
3.1 注册事件
给元素添加事件称为注册事件或者绑定事件。注册事件有两种方式:传统方式和方法监听注册方式。
- 传统注册方式
- 利用on开头的事件。
- 注册事件具有唯一性,也就是同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数会覆盖之前注册的处理函数
- 方法监听注册方式
- W3C推荐的方式
- addEventListener()是一个方法
- IE9之前不支持此方法,可使用attachEvent()代替
- 同一个元素同一个事件可以注册多个监听器,会按照注册的顺序依次执行
- addEventListener 事件监听方式
-
语法:
eventTarget.addEventListener(type, listener[, useCapture])
- type:事件类型字符串,要带引号,比如 'click'、'mouseover',这里不用带on
- listener:事件处理函数,事件发生时,会调用该监听函数,写函数名时不用加()
- useCapture:可选参数,是一个布尔值,默认为false,false为冒泡阶段,true为捕获阶段。
- attachEvent(type, listener)
- ie8之前使用的方法,一般不使用
- type:事件类型字符串,要带引号,要带on
3.2 删除事件(解绑事件)
移除事件时,要给事件处理函数先去个名字,然后移除。
- 传统方式解绑
- element.事件名 = null;
- 方法监听注册方式
- eventTarget.removeEventListener(type, listener)
- ie8之前的删除事件方式
- eventTarget.detachEvent(type, listener)
3.3 DOM 事件流
事件发生时会在元素节点之间按照特定顺序传播,这个传播过程即DOM事件流。
- JS代码只能执行捕获或冒泡阶段
- onclick 和 attachEvent 只能得到冒泡阶段
- addEventListener(type, listener[, useCapture]) 中第三个参数决定是否为捕获阶段,true为捕获阶段;false或不写为冒泡阶段
- 实际开发中,很少使用事件捕获,更关注事件冒泡
- 有些事件是没有冒泡的,比如:onblur、onfocus、onmouseenter、onmouseleave
3.4 事件对象
div.onclick = fuction(event){
console.log(event);
// 兼容IE6 7 8
e = e || window.event;
};
- 监听函数的参数就是事件对象,当作形参来看。
- event 对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态等
- 可以将事件对象理解为跟事件(鼠标点击或按键盘)相关的一系列信息数据的集合,有很多属性和方法
3.4.1 常见事件对象的属性和方法
- e.target:返回触发事件的对象(元素)
- this 和 currentTarget 作用一样。this 返回的注册事件的对象,e.target 返回的是触发事件的对象
- 不兼容IE 678。IE 678 用 e.srcElement;
- e.type:返回事件的类型。返回的是不带on的
- e.preventDefault():该方法阻止默认事件(默认行为)标准,比如:让链接不跳转
- e.returnValue:IE 678 可以使用这个属性阻止默认事件行为
- return false; 可以利用return阻止默认事件行为,没有兼容性问题。特点:return之后的代码不执行。
- 对于addEventListener注册的事件,只能用e.prentDefault()阻止默认行为。
- 对于传统注册方法,可以使用e.returnValue和return false两种方法。
- e.stopPropagation():阻止冒泡事件
- 具有兼容性,不支持IE678
- e.cacelBubble = true; 支持IE 678浏览器。
3.5 事件委托(代理、委派)
事件委托也称为事件代理。原理:不给每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理设置每个子节点。
3.6 常用的鼠标事件
- contextmenu :用来显示上下文菜单,主要用于取消默认的上下文菜单
- selectstart:开始选中,一般用于禁止鼠标选中
- mousemove:鼠标移动事件,只要移动就会触发
3.7 鼠标事件对象 MouseEvent
- e.clientX,e.clientY:展示鼠标在可视区的x坐标(距离左沿)和y坐标(距离上沿)
- e.pageX,e.pageY:展示鼠标在页面文档的x坐标和y坐标,IE9支持
-
- e.screenX,e.screenY:距离屏幕左沿和上沿的距离
3.8 常用的键盘事件
- onkeyup:某个按键被松开时被触发
- onkeydown:某个按键被按下时触发
- keyup 和 keydown 不区分字母大小写
- onkeypress:某个按键被按下时触发,但是它不识别功能键,比如ctrl shift 箭头等
- 三个事件的执行顺序:onkeydown --> onkeypressd --> onkeyup
- keypress 区分字母大小写
3.9 键盘事件对象 keyboardevent
- e.keyCode:返回用户按下的键的ASCII值
- onkeydown 和 onkeyup 不区分字母大小写,onkeypress 区分大小写,但是不识别功能键。
- 平时常用的还是keydown 和 keyup
4 BOM
BOM(Brower Object Model)是浏览器对象模型,提供了独立于内容而于浏览器窗口交互的对象,核心对象是window。BOM学习的是浏览器窗口交互的一些对象。
4.1 BOM的构成
BOM比DOM更大,BOM包含了DOM。BOM中最大的顶级对象是window,包含了document、location、navigation、screen、history等。window对象有双重角色:
- 它是JS访问浏览器的一个接口
- 它是一个全局对象,定义在全局作用域中的变量、函数都会变成window对象的属性和方法
- 调用时可以省略window
- window下有一个特殊属性window.name,随意不要定义一个变量名是name
4.2 window 对象的常见事件
4.2.1 窗口加载事件
(1)window.onload是窗口加载事件,当文档内容加载完成时(包括图片、样式、JS文件等)才会触发该事件
window.onload = function(){}
// 或者
window.addListener('load', function(){})
- 有了window.onload就可以把JS代码写到页面元素的上方,因为onload是等页面内容加载完毕才会执行处理函数
- window.onload传统注册事件方式只能写一次,如果有多个,会以最后一个window.onload为准
- 如果使用addListener则没有限制
(2)DOMContentLoaded
document.addEventListener('DOMContentLoaded',function(){})
- DOMContentLoaded事件触发时,仅当DOM加载完成(也就是标签加载完成,不包括样式表、图片、flash等)就会执行,加载速度比onload快很多
- IE9以上才支持
- 如果页面图片很多的话,使用onload,用户访问到触发会需要较长的时间,交互效果就不能实现,影响用户体验;这种情况,使用DOMContentLoaded就会好很多。
4.2.2 调整窗口大小事件
window.onresize = function(){};
window.addEventListener('resize',function(){});
window.onresize是调整窗口大小加载事件,当触发时就调用的处理函数
- 只要窗口大小发生像素变化,就会触发这个事件
- 我们经常利用这个事件完成响应式布局
- window.innerWidth 获取当前页面宽度
- window.innerHight 获取当前页面高度
4.2.3 定时器
(1)设置定时器 setTimeout()
window.setTimeout(调用函数,[延迟的毫秒数]);
window.setInterval(调用函数,[间隔的毫秒数]);
- setTimeout():设置一个定时器,在该定时器到期后执行调用函数
- setInterval():设置一个定时器,重复调用一个函数,每隔这个时间,就调用一次回调函数
- window可以省略
- 这个调用函数可以直接写函数,也可以写函数名或采取字符串 '函数名()' ,三种方式,但是字符串的方式不推荐
- 延迟的毫秒数默认是0,如果要自定义,单位必须是毫秒,单位可以不写
- setTimeout()这个调用函数我们称为回调函数callback
// 例如
window.setTimeout(function(){
alert('直接将函数体写到调用函数里,延迟2秒');
},2000);
window.setTimeout(fn,2000);
function fn(){
alert('这是将函数名写到调用函数里,延迟2秒');
};
// 为了区分不同的定时器,经常给定时器加标识符
var timer = window.setTimeout(fn,2000);
(2)停止计时器
window.clearTimeout(timeoutID);
window.clearInterval(timeoutID);
clearTimeout()取消了先前通过setTimeout()建立的定时器
- window也可以省略
- 里面的参数就是定时器的标识符
4.3 this 指向问题
一般情况下,this的最终指向是调用它的对象。
- 全局作用域或者普通函数中 this 指向全局对象 window
- 定时器里的 this 也指向全局对象 window
- 方法调用中谁调用该方法,this 指向谁
- 构造函数中 this 指向构造函数的实例
4.4 JS执行机制
如果某句代码需要执行很长时间,就会导致后面的代码停滞,用户体验不好。为了解决这个问题,HTML5提出了Web Worker 标准,允许JS脚本创建多个线程。于是,JS 中出现了同步和异步。
- 同步:前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的
- 异步:在做一件事时,因为这件事会花费较长的时间,在做这件事的同时,还可以处理其他事情,就称为异步
4.4.1 同步任务和异步任务
- 同步任务:同步任务都在主线程上执行,形成一个执行栈
- 异步任务:JS的异步是通过回调函数实现的,异步任务又三种类型
- 普通事件。如:click、resize等
- 资源加载。如:load、error等
- 定时器。如:setInterval、setTimeout等
4.4.2 执行机制
- 先执行执行栈(主车道)中的同步任务
- 将异步任务(回调函数)放入任务队列(应急车道)中
- 当执行栈(主车道)中的同步任务执行完毕,系统会按次序读取任务队列(应急车道)中的异步任务。被读取的异步任务结束等待状态,进入执行栈,开始执行。
4.4.5 异步进程处理和事件循环
- 异步进程处理:处理回调函数,决定回调函数是否放进任务队列中。比如普通事件click,只有当点击之后,异步进程处理才会将点击对应的回调函数放进任务队列中。
- 事件循环:由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制称为事件循环。
4.5 location 对象
用于获取或设置窗体的URL,并可以用于解析URL。因为这个属性的返回是一个对象,所以我们也将这个属性称为location对象
4.5.1 URL
语法格式为:
protocol://host[:port]/path/[?query]#fragment
协议://域名/路径/[参数]#片段
4.5.2 location 常见的属性
- location.href:获取或设置整个URL
- location.host:返回主机(域名)
- location.port:返回端口号,如果没有,则返回空字符串
- location.pathname:返回路径
- location.search:返回参数
- location.hash:返回片段。#后面的内容,常见于链接锚点
4.5.3 location常见的方法
- location.assign():跟href一样,可以跳转页面(也称为重定向页面),可以回退
- location.replace():替换当前页面,因为不记录历史,不能后退页面
- location.reload():重新加载页面,相当于刷新按钮。如果参数为true,强制刷新ctrl+f5
- 如果页面缓存后,刷新会从本地提取,强制刷新就是从服务器里重新加载
4.6 navigator 对象
navigator对象包含有关浏览器的信息,它有很多属性,最常用的是userAgent,该属性可以返回客户机发送服务器的user-agent头部的值。
4.7 history 对象
window 对象给我们提供了一个history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。一般不常用,在OA系统上可能会用到。
- back():后退功能
- forward():前进功能
- go(参数):前进后退功能,参数如果是1,前进一个页面;如果是-1,后退1个页面