前言

Api:应用程序接口,开发的工具;

本文介绍JavaScript在浏览器的Webapi,记录了自己的学习过程。

DOM文档对象模型

获取元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
document.getElementById('id') // id获取,返回的是元素对象,没有为null
// 可以返回的元素对象,更好的查看里面的属性和方法
console.dir(document.getElementById('id'))
// 返回的是数组,一个为伪数组,空为空的数组
document.getElementsByTagName('标签名')
// 获取某个父元素里面的标签元素
var ol = document.getElementsByTagName('ol')[0]
var lis = ol.getElementsByTagName('li')// 不包含父元素
// HTML新增
// 返回结果和Tag一样
document.getElementsByClassName('类名')
// 根据指定选择器返回第一个元素对象(参数是css选择器),返回和id一样
document.querySelector('选择器');
// 返回所有的,返回值和Tag一样
document.querySelectorAll('选择器');
// 获取body元素
var body = document.body
// 获取html元素
var html = document.documentElement

事件基础

  • 一些常见的鼠标事件

  • 其他事件
ondblclick 鼠标双击
onchange 文本内容或下拉菜单中的选项发生改变
onload 网页文档加载事件
onunload 关闭网页时
onsubmit 表单提交事件
onreset 重置表单时
  • 属性操作

可以不用事件直接更改

1
2
3
4
5
6
// 从起始位置到终止位置的内容, 但它去除 html 标签, 同时空格和换行也会去掉
element.innerText
// 起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行
// 注意HTML都是大写
element.innerHTML
// 可以获取元素的这两个属性

其他的标签属性:src、href 、id、alt、title

表单元素的属性操作

type、value、checked、selected、disabled

样式属性操作

element.style 行内样式操作 、element.className 类名样式操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 自定义属性
// 主要获得自定义的属性 (标准) 我们程序员自定义的属性
element.getAttribute('属性名')
// 主要设置自定义的属性 (标准)
// 注意className直接是class
element.setAttribute('属性名','属性值')
// 移除属性
element.removeAttribute('属性')

// H5规定自定义属性data-开头做为属性名并且赋值。
比如 <div data-index="1" data-list-name="div"></div>

element.setAttribute('data-index', 2)
element.dataset.listName // 驼峰命名
element.dataset.index

节点操作

方法 意义
children 子元素节点,不包含换行等
childNodes 子节点,包含文本、换行等
parentNode 父节点,注意是单数
previousSibling 前一个同辈节点,包括文本节点、注释节点即回车、换行、空格、文本等
previousElementSibling 前一个同辈节点,不包括文本节点、注释节点
nextSibling 后一个同辈节点,包括文本节点、注释节点即回车、换行、空格、文本等
nextElementSibling 后一个同辈节点,不包括文本节点、注释节点等
firstChild 第一个子节点,包含文本
firstElementChild 第一个子节点,不包含文本
lastChild 最后一个子节点,包含文本
lastElementChild 最后一个子节点,不包含文本

创建节点

方法 意义
appendChild() 在最后面追加
insertBefore() 参数 1: 要插入的节点 参数 2: 作为参照的节点,如果为 null,与 appendChild 效果相同
replaceChild() 替换节点 参数 1: 要插入的节点 参数 2: 要替换的节点
removeChild() 移除节点 参数: 要移除的节点
cloneNode() 复制节点 参数(可选):true,克隆时包含子元素
createElement 创建元素节点
createTextNode 创建文本节点
1
2
3
4
5
6
// 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
document.write()
// 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
element.innerHTML
// 创建多个元素效率稍低一点点,但是结构更清晰
document.createElement()

注册事件

注册事件有两种方式:传统方式和方法监听注册方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 传统方式,利用 on 开头的事件onclick
// 同一个元素同一个事件只能设置一个处理函数,最
后注册的处理函数将会覆盖前面注册的处理函数
// 特点: 注册事件的唯一性

btn.onclick = function() {}

// 方法监听注册方式 (ie9以上支持)w3c标准
// 同一个元素同一个事件可以注册多个监听器
(函数,事件处理程序)按注册顺序依次执行;
// 注意:事件类型需要加引号,且不能带on
eventTarget.addEventListener(type, listener[, useCapture])
// useCapture:可选参数,是一个布尔值,默认是 false。
btn.addEventListener('click',function(){})

// 了解attachEvent(ie9以下支持)
// 需要接上on
eventTarget.attachEvent(eventNameWithOn, callback)

删除事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 传统方式
div.onclick = function(){
console.log(999)
div.onclick = null
}

// addEventListener
// 注意绑定事件不能使用匿名函数,参数中不能写(),不是调用;
function fn(){ console.log(111) }
div.addEventListener('click', fn)
div.removeEventListener('cilck', fn);

// 了解attachEvent(与addEventListener同理)
function fn(){ console.log(111) }
div.attachEvent('onclick', fn)
div.detachEvent('oncilck', fn);

Dom事件流

事件发生时会在元素节点之间按照特定的顺序传播,事件的传播过程就是DOM事件流;

三个阶段:捕获阶段(从上往下或者从父到子) 、当前目标阶段 (触发事件)、冒泡阶段(从子到父)

注意:

  1. JS 代码中只能执行捕获或者冒泡其中的一个阶段。

  2. onclick 和 attachEvent 只能得到冒泡阶段。

  3. addEventListener(type, listener[, useCapture])第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。

  4. 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave

事件对象

1
2
3
4
5
6
// event对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
// 简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面
eventTarget.onclick = function(event) {}
eventTarget.addEventListener('click', function(e) {})
// 兼容ie6 7 8只支持window.event
e = e || window.event;

事件对象属性方法

1
2
3
4
5
6
// this和event.target的区别
// this是事件绑定的元素,这个函数的调用者(绑定这个事件的元素)
// e.target 是事件触发的元素
// ul里面多个li,给ul绑定事件;this是ul,e.target点击哪个li或者ul,就是点击的那个
// currentTarget和this相似,都是绑定事件的元素
// 了解ie 6 7 8 使用e.target -> e.srcElement

阻止默认事件

1
2
3
4
5
6
// 传统方式
div.onclick = function(e){
e.preventDefault() // 是一个方法(低版本ie不支持)
e.returnValue // ie6 7 9 ,是一个属性
return false // 没有兼容性问题,但是在方法监听注册中不起作用
}

阻止事件冒泡

1
2
3
4
5
6
// 标准写法:利用事件对象里面的 stopPropagation()方法
div.onclick = function (e){
e.stopPropagation() // 标准
}
// 了解低版本ie6 7 8
e.cancelBubble = true

事件委托

1
2
3
// 原理:事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
// 如ul中有多个li,给父绑定事件就可以找到每个li
ul.addEventListener('click',function(e){conlose.log(e.target)})

常用的鼠标事件

1
2
3
4
5
6
7
8
9
10
// 禁止鼠标右键菜单
// contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单

document.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
// 禁止鼠标选中(selectstart 开始选中)
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})

鼠标事件对象

1
2
// e.clientX,e.clientY的值是可视区域,不管页面是否有滚动条
// e.pageX,e.pageY的值是document文档的坐标

常用的键盘事件

三个事件的执行顺序是: keydown – keypress — keyup,一直按着会一直触发keydown和keypress

键盘事件对象

1
2
3
4
5
6
7
8
document.onkeyup = function (e) {
console.log(e.key)
console.log(e.code)
// 被弃用,得到的是ASCⅡ值,注意onkeyup和onkeydown不区分大小写,返回大写
// 可以使用onkeypress
console.log(e.keyCode)
console.log(e.key.charCodeAt())
}

BOM浏览器对象模型

BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心 对象是 window。

注意:不要使用name作为变量,name是属于window的属性

window对象常见的事件

1
2
3
4
5
6
7
8
9
// 加载事件,script可以放在任何位置,页面加载完
window.addEventListener('load',function () {})
// 仅当DOM加载完成,不包括样式表,图片,flash等等,加载速度比load快
document.addEventListener('DOMContentLoaded',function () {})

// 调整窗口大小事件,当窗口大小发生改变就会触发
window.onresize = function () {
console.log(window.innerWidth) // 获取屏幕的宽度(innerHeight)
}

定时器

1
2
3
4
5
6
7
8
9
10
11
// setTimeout(延迟执行),调用不要写f(),否者直接调用
function f() { alert(1) }
var time = setTimeout(f,3000)
var time = setTimeout('f()',3000) // 函数字符串不推荐
// 停止定时器
clearTimeout(time)

// setInterval(定时执行重复执行)
var time = null
tiem = setInterval(f,1000)
clearInterval(time)

this的指向

  1. 全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)

  2. 方法调用中谁调用this指向谁

  3. 构造函数中this指向构造函数的实例

JS执行队列

1
2
3
4
5
6
7
8
9
10
// 输出结果是1 2 3,定时器里的回调函数属于异步
console.log(1);
setTimeout(function () {
console.log(3);
}, 0);
console.log(2);

// 执行机制:先执行执行栈中的同步任务,异步任务放入任务队列中,
// 同步任务执行完毕,系统就会按次序读取任务队列中的异步任务
// 事件循环event loop:主线程不断的重复获得任务、执行任务、再获取任务、再执行

location 对象

1
2
3
4
5
6
// location属性
location.href = 'xxxx' // 跳转到某页面
location.search // 获取url的参数
// location方法
// 注意:assign和replace的区别,前面有记录历史;后不记录历史
location.reload(true) // 强制刷新,相当于Ctrl+f5;不加就是普通刷新

navigator 对象包含有关浏览器的信息,常用的是userAgent返回由客 户机发送服务器的user-agent头部的值;可以查看是pc还是移动端实现加载不同页面;

history 对象

1
2
3
history.forward() // 前进
history.back() // 后退
history.go() // 具体的数字,1前进、-1后退、0刷新;

网页特效与其他

元素偏移量 offset

1
2
3
4
5
6
7
8
// 获得元素距离带有定位父元素的位置
// 注意:是相对于带有定位的父元素(无论什么定位),没有就是相对于body
console.log(div.offsetLeft)
// 获取元素的宽高
// 注意:content-box包括padding border;border-box没有
console.log(div.offsetWidth)
// 获得带有定位的父元素
console.log(div.offsetParent)

offset与style的区别

style 只能得到行内样式表中的样式值,style标签里的获取不到;

style.width获得的是带有单位的字符串 ,不包含padding和border的值 ,可以赋值;

offsetWidth只能获取不能赋值;(其他的属性也不能如offsetLeft)

元素可视区client

注意:和offsetWidth的区别,clientWidth不包含边框

立即执行函数

1
2
3
4
5
6
7
8
9
// 立即执行函数: 不需要调用,立马能够自己执行的函数
// 函数可以取名,但是不能调用
(function sum(a, b) {
console.log(a + b);
var num = 10; // 里面定义的是局部变量
})(1, 2); // 第二个小括号可以看做是调用函数
// 注意有两个立即执行函数中间需要用;隔开否者会报错
(function(){}()) // 第二种写法
// 最大的好处就是局部变量,变量名不会冲突
1
2
3
4
5
6
7
// 物理像素比,pc是1,而手机则是2或者其他
var dpr = window.devicePixelRatio || 1
// window的pageshow事件,页面一显示就会触发,load没有刷新就不会触发如有缓存等情况
window.addEventListener('pageshow', function(e) {
// e.persisted是true,缓存加载过来的也会触发
if (e.persisted) {}
})

元素滚动scroll

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// scrollHeight和clientHeight差不多
// 但是当元素高固定,里面内容超出时,就会显示内容文字的高度,而client不会
console.log(div.scrollHeight);
console.log(div.clientHeight);
// scroll滚动事件当我们滚动条发生变化会触发的事件
div.addEventListener('scroll', function() {
console.log(div.scrollTop);
})
// scrollTop是内容元素有滚动条之后,内容上侧超出的高度,如果有边框局包含它

// 页面被卷去的头部:可以通过window.pageYOffset获得
// 如果是被卷去的左侧 window.pageXOffset

// 注意:元素被卷去的头部是 element.scrollTop
// 如果是页面被卷去的头部 则是 window.pageYOffset

鼠标事件一些区别

onmouseover、nmouseout:鼠标移动到自身时候会触发事件,同时移动到其子元素身上也会触发事件

onmouseenter、onmouseleave:鼠标移动到自身是会触发事件,但是移动到其子元素身上不会触发事件

动画

注意:定时器可以赋值某个对象的属性,可以节约内存资源,不需要使用字符串;

​ 封装的动画函数中,回调函数是在动画结束后再触发;

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
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()

// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';

}, 15);
}
1
2
// 自动调用点击
div.click()

移动端网页特效

触摸事件对象

1
2
3
4
5
6
// 示例
div.addEventListener('touchmove', function(touchEvent) {
console.log(touchEvent.targetTouches[])
// 阻止屏幕滚动的默认行为,屏幕有滚动条时,移动元素屏幕不会滚动。
e.preventDefault();
});