前端学习——Web APIs (DOM+BOM)

目录

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新增的方法

  1. getElementsByClassName('类名')
    1. 根据类名返回元素对象的集合
    2. 这里的类名是不需要加符号的,直接写类名即可,如:'box'
  2. querySelector('选择器') 
    1. 根据指定选择器返回第一个元素对象
    2. 因为选择器不确定是类选择器还是id选择器,所以选择器要加符号,如:'.box','#id5','li'
  3. querySelectorAll('选择器')
    1. 根据指定选择器返回所有元素对象
    2. 还是以伪数组的形式

2.2.4 获取特殊元素

  1. 获取 body 元素:document.body
  2. 获取 html 元素:document.documentElement

2.3 事件基础

事件就是触发--响应机制。事件由三部分组成:事件源、事件类型、事件处理程序。

  • 事件源:事件被触发的对象
  • 事件类型:如何触发?什么事件?比如鼠标点击
  • 事件处理程序:通过一个函数赋值的方式完成。

2.4 操作元素

2.4.1 改变元素内容

  1. element.innerText:从起始位置到终止位置的内容,不识别 html 标签,同时空格、换行也会去掉
  2. element.innerHTML:从起始位置到终止位置的内容,识别 html 标签,同时保留空格和换行。一般用这个。
    1. 这两个属性是可读写的,可以获取元素里面的内容。如:标签.innerText,标签.innerHTML 。
    2. innerText不识别 html 标签,innerHTML 识别 html 标签。

2.4.2 改变元素属性内容

可以使用this,this指向事件函数的调用者。

  1. 常用的元素属性有:innerText、innerHTML、src、href、id、alt、title
  2. 表单属性操作
    1. value:改变表单里面的内容。用 innerHTML 是没有效果的。
    2. disabled:表单被禁用,点击后被禁用。disabled = true
    3. type:改变表单的类型。应用:点击按钮,显示密码
    4. onfocus:获得焦点
    5. onblur:失去焦点
  3. 样式属性操作:元素的大小、颜色、位置等
    1. element.style:行内样式操作。如:div.style.backgroundColor
      1. JS 里面的样式采用驼峰命名法,如:fontSize、backgroundColor;
      2. JS 修改样式后,产生的是行内样式,CSS 权重比较高;
      3. 若样式比较少,功能简单的情况下使用。
    2. element.className:类名样式操作
      1. 修改当前元素的类名,例如:this.className = 'change';
      2. 注意,类名不需要加点。
      3. 适合样式较多,功能复杂的情况。
      4. 设置后,会覆盖掉原先的类名。
      5. 如果想保留原先的类名,可以像CSS一样用空格分隔。如:this.className = '原来的类名 修改的类名'。

2.4.3 排他思想

如果又同一组元素,想要某一个元素的样式改变,先把其他元素的样式去掉,再设置某一个元素的样式。这样的想法称为排他思想。

2.4.4 自定义属性的操作

元素属性可以自定义。获取属性值的方法:

  1. element.属性:获取元素本身自带的属性,如id、class等。
  2. getAttribute('属性'):获取元素自定义的属性,也可以获取内置属性。

设置元素属性值

  1. element.属性 = '值':更改元素内置属性。
  2. element.setAttribute('属性','值'):主要针对自定义属性,也可以更改内置属性。
    1. 属性中class比较特殊,应该写className,就可以更改class的值

移除属性

  1. element.removeAttribute('属性'):移除元素的某个属性

2.4.5 H5 自定义属性

自定义属性的目的是为了保存并使用数据,有些数据可以保存到页面中。为了区分内置属性和自定义属性,H5规定自定义属性以 ‘data-’ 开头作为属性名,并赋值。

  1. .setAttribute('自定义属性名',属性值):通过JS设置自定义属性的值。
  2. .getAttribute('data-自定义属性名'):获取自定义属性的值,更常用。
  3. element.dataset.属性名或者element.dataset['自定义属性名']
    1. H5新增的方法,ie11才开始支持。
    2. dataset是一个存放了所有以data开头的自定义属性的对象。
    3. 若自定义属性名里有多个 - 链接的单词,获取时,用驼峰命名法。
    4. 如 data-list-name = 'andy',获取时,应该是 element.dataset.listName 或者element.dataset['listName']。
    5. dataset方法无法获得没有以data开头的自定义属性。

2.5 节点操作

获取元素之前都是使用DOM提供的方式,除此之外还可以使用父子级关系获取,也就是节点操作

  • 文档中所有的内容都可以称为节点,包括:文档节点、文本节点、元素节点、属性节点等。
  • 节点至少拥有nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值)三个基本属性
    • 元素节点 nodeType为1。开发中,主要操作的是元素节点。
    • 属性节点 nodeType为2。
    • 文本节点 nodeType 为3,文本节点包括文字、空格、换行等。

2.5.1 节点层级

父子层级

  1. node.parentNode:得到的是离元素最近的父级节点。找不到父节点返回null。
  2. parentNode.childNodes:得到父节点的所有的子节点,包含元素节点、文本节点(换行)等。
    1. 通过元素节点类型来判断获得的节点是否为元素节点。
    2. 元素节点类型为1,属性节点类型为2,文本节点类型为3。
  3. parentNode.children:获取所有的子元素节点,返回一个伪数组。实际开发常用的方法。
    1. parentNode.children[0]:获取第一个子元素节点
    2. parentNode.children[parentNode.children.length - 1]:获取最后一个子节点
  4. parentNode.firstChild:获取第一个子节点,不管是文本节点还是元素节点
  5. parentNode.lastChild:获取最后一个子节点,不区分文本还是元素
  6. parentNode.firstElementChild:获取第一个子元素节点,找不到返回null
  7. parentNode.lastElementChild:获取最后一个子元素节点,找不到返回null
    1. firstElementChild和lastElementChild有兼容性限制,ie9以上才支持

兄弟层级

  1. node.nextSibling:返回当前元素的下一个兄弟节点,找不到返回null,包含文本节点
  2. node.previousSibling:返回当前元素的上一个兄弟节点,找不到返回null,包含文本节点
  3. node.nextElementSibling:返回当前元素的下一个兄弟元素节点
  4. node.previousElementSibling:返回当前元素的上一个兄弟元素节点
    1. nextElementSibling和previousElementSibling有兼容性限制,ie9以上才支持
    2. 为了解决兼容性问题,可以自己封装一个兼容性函数
    3. function getNextElementSibling(element){
          var el = element;
          while (el = el.nextSibling) {
              if (el.nodeType === 1){   
                  return el;
              }
          }
          return null;
      }

2.5.2 创建节点

  1. document.creatElement('tagName'):创建节点

2.5.3 添加节点

添加节点分为两步:1)创建元素;2)添加元素。

  1. node.appendChild(child):其中node 是父级,child是子级。
    1. 参数不用带引号
    2. 新添加的节点,会放在父元素的最后面,类似于数组中的push
    3. 例如:ul.appendChild(li);
  2. node.insertBefore(child, 指定元素)
    1. 将节点插入到指定元素的前面
    2. 例如:ul.insertBefore(li,ul.children[0]) ,插入到第一个元素的前面

2.5.4 删除节点

  1. node.removeChild(child):删除一个子节点,返回删除的节点
    1. node是父节点,child是孩子节点
  2. 应用:留言板删除
    1. 注册事件用小点,不用冒号!
    2. textarea的值是value,不是innerHTML;
    3. 如果不想让a 链接跳转,可以给href上写javascript: ;

2.5.5 复制节点

  1. node.cloneNode():将节点Node复制一份
    1. 和创建节点一样,需要先复制,再添加到父节点中,才会显示出来
    2. 若参数为空或false,表示浅拷贝,只复制节点标签,不复制内容
    3. 若参数为true为深拷贝,复制节点标签及里面的内容。深拷贝的标签和原标签一起改变

2.5.6 三种动态创建元素区别 (了解)

  1. document.write()
    1. document.write(
      123
      );
    2. 如果页面文档流加档完毕,再调用这句话,会导致页面重绘。重新产生一个页面。
  2. element.innerHTML
    1. innerHTML创建多个元素的效率更高(不要拼接字符串,要采取数组形式拼接),结构稍微复杂
    2. 创建完毕,页面不会重绘
  3. document.createElement()
    1. 这两者执行上,没什么大的区别;他俩的区别可能会在面试的时候碰到!
    2. creatElemen()的执行效率稍微低,但是结构更清晰
    3. 创建完毕,页面不会重绘

2.6 事件操作

给元素注册事件,采用 事件源.事件类型 = 事件处理程序 的方式

  1. onclick:鼠标点击左键触发
  2. onmouseover:鼠标经过触发
    1. mouseover经过自身盒子触发,经过子盒子也会触发,因为子盒子会冒泡给父盒子,触发父盒子的事件
  3. onmouseenter:鼠标经过触发
    1. mouseenter只经过自身盒子触发,经过子盒子不会触发,因为mouseenter没有冒泡
    2. 跟mouseenter搭配鼠标离开的是mouseleave,同样不会冒泡
  4. onmouseout:鼠标离开触发
  5. onfocus:获得鼠标焦点触发
  6. onblur:失去鼠标焦点触发
  7. onmousemove:鼠标移动触发
  8. onmouseup:鼠标弹起触发
  9. onmousedown:鼠标按下触发
  10. contextmenu:控制显示上下文菜单,也就是右键菜单,主要用于程序媛取消默认的上下文菜单
  11. document.addEventListener('contextmenu', function(e){
        // 禁止显示右键菜单
        e.preventDefault();
    })
  12. selectstart:开始选中,一般用于禁止鼠标选中
  13. document.addEventListener('selectstart', function(e){
        e.preventDefault();
    })

3 事件高级

3.1 注册事件

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

  1. 传统注册方式
    1. 利用on开头的事件。
    2. 注册事件具有唯一性,也就是同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数会覆盖之前注册的处理函数
  2. 方法监听注册方式
    1. W3C推荐的方式
    2. addEventListener()是一个方法
    3. IE9之前不支持此方法,可使用attachEvent()代替
    4. 同一个元素同一个事件可以注册多个监听器,会按照注册的顺序依次执行
  3. addEventListener 事件监听方式
    1. 语法:

      eventTarget.addEventListener(type, listener[, useCapture])
    2. type:事件类型字符串,要带引号,比如 'click'、'mouseover',这里不用带on
    3. listener:事件处理函数,事件发生时,会调用该监听函数,写函数名时不用加()
    4. useCapture:可选参数,是一个布尔值,默认为false,false为冒泡阶段,true为捕获阶段。
  4. attachEvent(type, listener)
    1. ie8之前使用的方法,一般不使用
    2. type:事件类型字符串,要带引号,要带on

3.2 删除事件(解绑事件)

移除事件时,要给事件处理函数先去个名字,然后移除。

  1. 传统方式解绑
    1. element.事件名 = null;
  2. 方法监听注册方式
    1. eventTarget.removeEventListener(type, listener)
  3. ie8之前的删除事件方式
    1. eventTarget.detachEvent(type, listener)

3.3 DOM 事件流

事件发生时会在元素节点之间按照特定顺序传播,这个传播过程即DOM事件流。

前端学习——Web APIs (DOM+BOM)_第1张图片

  •  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 常见事件对象的属性和方法

  1. e.target:返回触发事件的对象(元素)
    1. this 和 currentTarget 作用一样。this 返回的注册事件的对象,e.target 返回的是触发事件的对象
    2. 不兼容IE 678。IE 678 用 e.srcElement;
  2. e.type:返回事件的类型。返回的是不带on的
  3. e.preventDefault():该方法阻止默认事件(默认行为)标准,比如:让链接不跳转
    1. e.returnValue:IE 678 可以使用这个属性阻止默认事件行为
    2. return false; 可以利用return阻止默认事件行为,没有兼容性问题。特点:return之后的代码不执行。
    3. 对于addEventListener注册的事件,只能用e.prentDefault()阻止默认行为。
    4. 对于传统注册方法,可以使用e.returnValue和return false两种方法。
  4. e.stopPropagation():阻止冒泡事件
    1. 具有兼容性,不支持IE678
    2. e.cacelBubble  = true; 支持IE 678浏览器。

3.5 事件委托(代理、委派)

事件委托也称为事件代理。原理:不给每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理设置每个子节点

3.6 常用的鼠标事件

  1. contextmenu :用来显示上下文菜单,主要用于取消默认的上下文菜单
  2. selectstart:开始选中,一般用于禁止鼠标选中
  3. mousemove:鼠标移动事件,只要移动就会触发

3.7 鼠标事件对象 MouseEvent

  1. e.clientX,e.clientY:展示鼠标在可视区的x坐标(距离左沿)和y坐标(距离上沿)
  2. e.pageX,e.pageY:展示鼠标在页面文档的x坐标和y坐标,IE9支持
  3. 前端学习——Web APIs (DOM+BOM)_第2张图片

  4. e.screenX,e.screenY:距离屏幕左沿和上沿的距离

3.8 常用的键盘事件

  1. onkeyup:某个按键被松开时被触发
  2. onkeydown:某个按键被按下时触发
    1. keyup 和 keydown 不区分字母大小写
  3. onkeypress:某个按键被按下时触发,但是它不识别功能键,比如ctrl shift 箭头等
    1. 三个事件的执行顺序:onkeydown --> onkeypressd --> onkeyup
    2. keypress 区分字母大小写

3.9 键盘事件对象 keyboardevent

  1. e.keyCode:返回用户按下的键的ASCII值
    1. onkeydown 和 onkeyup 不区分字母大小写,onkeypress 区分大小写,但是不识别功能键。
    2. 平时常用的还是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对象有双重角色:

  1. 它是JS访问浏览器的一个接口
  2. 它是一个全局对象,定义在全局作用域中的变量、函数都会变成window对象的属性和方法
    1. 调用时可以省略window
    2. 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(调用函数,[间隔的毫秒数]);
  1. setTimeout():设置一个定时器,在该定时器到期后执行调用函数
  2. setInterval():设置一个定时器,重复调用一个函数,每隔这个时间,就调用一次回调函数
    1. window可以省略
    2. 这个调用函数可以直接写函数,也可以写函数名或采取字符串 '函数名()' ,三种方式,但是字符串的方式不推荐
    3. 延迟的毫秒数默认是0,如果要自定义,单位必须是毫秒,单位可以不写
    4. 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的最终指向是调用它的对象。

  1. 全局作用域或者普通函数中 this 指向全局对象 window
  2. 定时器里的 this 也指向全局对象 window
  3. 方法调用中谁调用该方法,this 指向谁
  4. 构造函数中 this 指向构造函数的实例

4.4 JS执行机制

如果某句代码需要执行很长时间,就会导致后面的代码停滞,用户体验不好。为了解决这个问题,HTML5提出了Web Worker 标准,允许JS脚本创建多个线程。于是,JS 中出现了同步和异步。

  • 同步:前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的
  • 异步:在做一件事时,因为这件事会花费较长的时间,在做这件事的同时,还可以处理其他事情,就称为异步

4.4.1 同步任务和异步任务

  1. 同步任务:同步任务都在主线程上执行,形成一个执行栈
  2. 异步任务:JS的异步是通过回调函数实现的,异步任务又三种类型
    1. 普通事件。如:click、resize等
    2. 资源加载。如:load、error等
    3. 定时器。如:setInterval、setTimeout等

4.4.2 执行机制

  1. 先执行执行栈(主车道)中的同步任务
  2. 将异步任务(回调函数)放入任务队列(应急车道)中
  3. 当执行栈(主车道)中的同步任务执行完毕,系统会按次序读取任务队列(应急车道)中的异步任务。被读取的异步任务结束等待状态,进入执行栈,开始执行。

4.4.5 异步进程处理和事件循环

  • 异步进程处理:处理回调函数,决定回调函数是否放进任务队列中。比如普通事件click,只有当点击之后,异步进程处理才会将点击对应的回调函数放进任务队列中。
  • 事件循环:由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制称为事件循环。

4.5 location 对象

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

4.5.1 URL

语法格式为:

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

协议://域名/路径/[参数]#片段

前端学习——Web APIs (DOM+BOM)_第3张图片

 4.5.2 location 常见的属性

  1. location.href:获取或设置整个URL
  2. location.host:返回主机(域名)
  3. location.port:返回端口号,如果没有,则返回空字符串
  4. location.pathname:返回路径
  5. location.search:返回参数
  6. location.hash:返回片段。#后面的内容,常见于链接锚点

4.5.3 location常见的方法

  1. location.assign():跟href一样,可以跳转页面(也称为重定向页面),可以回退
  2. location.replace():替换当前页面,因为不记录历史,不能后退页面
  3. location.reload():重新加载页面,相当于刷新按钮。如果参数为true,强制刷新ctrl+f5
    1. 如果页面缓存后,刷新会从本地提取,强制刷新就是从服务器里重新加载

4.6 navigator 对象

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

4.7 history 对象

window 对象给我们提供了一个history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。一般不常用,在OA系统上可能会用到。

  1. back():后退功能
  2. forward():前进功能
  3. go(参数):前进后退功能,参数如果是1,前进一个页面;如果是-1,后退1个页面

你可能感兴趣的:(前端,学习,javascript)