知识点整理来源于网上。详细的介绍推荐直接看API文档。
DOM 功能
对元素的增查删改
① 查询某个元素
② 查询某个元素的祖先、兄弟以及后代元素
③ 获取、修改元素的属性
④ 获取、修改元素的内容
⑤ 创建、插入和删除元素
节点分类
根据标签确定
① 文档节点(Document):整个XML、HTML文档
② 元素节点(Element):每个XML、HTML元素
③ 属性节点(Attr):每个XML、HTML元素的属性
④ 文本节点(Text):每个XML、HTML元素内的文本
⑤ 注释节点(Comment):每个注释
注意:这里的Document节点为总称,具体可分为XMLDocument和HTMLDocument,同理Element也可分为XMLElement和HTMLElement。
节点层次
节点彼此都有等级关系:父节点、兄弟节点、子节点等等。
节点属性
-
innerHTML:以HTML代码格式获取或设置节点的内容,会以HTML的形式呈现。比如:node.innerHTML="<input type='button' value='按钮' />" 将会显示一个按钮。
document.getElementById('div').innerHTML="<input type='button' value='按钮' />";
innerText:获取或设置节点的文本内容,以文本字符串的形式获取或设置节点的内容。nodeName、nodeValue以及nodeType等。
-
nodeName:获取节点名称,只读属性
console.log( document.nodeName ); // => #document:文档节点
console.log( document.body.nodeName ); // => BODY:元素节点
console.log( document.getElementById('div').nodeName ); // => DIV:元素节点
console.log( document.getElementById('div').attributes.style.nodeName ); // => style:属性节点
```
-
nodeValue:获取或设置节点的值,文档节点、元素节点此属性返回null
console.log( document.nodeValue ); // => null:文档节点
console.log( document.body.nodeValue ); // => null:元素节点
console.log( document.getElementById('div').nodeValue ); // => null:元素节点
console.log( document.getElementById('div').attributes.style.nodeValue ); // => width:200px;height:100px;border:1px solid black;:style属性的值
document.getElementById('div').attributes.style.nodeValue = ' width:200px;height:200px'; // 设置style属性的值
```
- nodeType:返回节点类型,只读属性
文档节点(Document) 9
元素节点(Element) 1
属性节点(Attr) 2
文本节点(Text) 3
测试
console.log( document.nodeType ); // => 9:文档节点
console.log( document.body.nodeType ); // => 1:元素节点
console.log( document.getElementById('div').nodeType ); // => 1:元素节点
console.log( document.getElementById('div').attributes.style.nodeType ); // => 2:属性节点
获取 HTML 元素节点方法
getElementById(id)
获取指定ID的元素
注意:
① HTML元素ID是区分大小写的。
② 若没有找到指定ID的元素,返回null。
③ 若一个父节点下面有多个相同ID元素时,默认选取第一个(而不是层级最高的)。
getElementsByName(name)
返回一个包含指定name名称的的元素数组
document.getElementsByName('Btn'); // 返回一个name为btn的元素数组
getElementsByTagName(elementName)
返回一个指定标签名称的的元素数组
document.getElementsByTagName('div'); // 返回一个标签为div的元素数组
DOM对象
- Document 对象:表示文档树的根节点,大部分属性和方法都是对元素进行操作。
- Element 对象:表示文档中的元素,可包含为元素节点、文本节点以及注释节点。
- Attr 属性对象:表示一个Element节点的属性。可获取、添加、修改指定的属性。
- Event 对象:表示事件发生时的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态等等。
直接查看API文档
HTML 事件
- 事件可表示为动作。以鼠标为例,移动、点击、悬停都是一种动作,也是事件。
- 事件类型(event type):表示事件的类型。如:MouseEvent(鼠标事件)、KeyboardEvent(键盘事件)。
- 事件名称(event name):表示事件的名称。如:click(单击)、dblclick(双击)。
- 事件目标(event target):表示与发生事件相关的目标对象。
5.事件处理程序(event handler):指处理事件的函数,即发生事件时,需调用的函数。 - 事件对象(event object):事件发生时,表事件的状态,比如事件发生的目标、键盘按键的状态、鼠标的位置、鼠标按钮的状态等等。事件触发时,通过参数传递给事件处理程序。
HTML元素中的事件处理程序属性名称是以"on"为前缀,紧跟着事件的名称。如:onclick、onload。
事件类型
每一个事件都有归属的事件类型,不同的事件类型具有不同的信息。
- UIEvent Types :用户界面事件类型;当用户与页面上的元素交互时触发
- 包含事件:load、unload、abort、error、select、resize、scroll。
- FocusEvent :焦点事件; 当元素获得或失去焦点时触发
- 包含事件:blur、focus、focusin、focusout。
- MouseEvent Types :鼠标事件类型;当鼠标在页面上执行操作时触发
- 包含事件:click、dblclick、mousedown、mouseenter、mouseleave、mousemove、mouseout、mouseover、mouseup。
- WheelEvent Types :滚轮事件类型;当鼠标滚轮时触发
- 包含事件:wheel。
- KeyboardEvent Types :键盘事件类型;当键盘在页面上执行操作时触发
- 包含事件:keydown、keyup、keypress。
- CompositionEvent Types:复合事件类型;当为IME输入字符时触发
- 包含事件:compositionstart、compositionupdate、compositionend。
Event 事件对象(这部分比较重要)
Event 对象表示事件发生时的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态等等。
获取方式:事件触发时的第一个参数 或者 事件触发时调用window.event对象。
document.getElementById('btn').addEventListener('click', function(e){
console.log(window.event==e); // => true :触发时两者是一样
- 冒泡事件:当子元素触发某一事件时,父元素会触发相同时间(事件为允许冒泡)。
- 阻止后续处理程序:通过addEventListener()方法可以给元素的同一事件注册多个处理程序,在某个事件中调用了stopImmediatePropagation() 方法后,后面已经注册的处理程序将不会执行。比如,某个元素在click事件上注册了3个函数,在第2个函数上调用了stopImmediatePropagation()方法,第3个函数不会执行。
具体的看文档
- currentTarget 与 target 属性的区别
- currentTarget :获取正在处理此事件的对象。
- target :获取触发此事件的对象。
冒泡阶段时两者的区别: 假设body和Button元素都注册了click事件;当点击Button元素时,body的click事件也会触发,此时在body的click事件内,currentTarget指向body元素,target指向Button元素。
Event 事件的注册与注销(类比iOS中的事件)
- 注册事件:介绍通过元素的事件属性、addEventListener()以及attachEvent()方法进行事件的注册。
- 注销事件:介绍通过removeEventListener()、detachEvent()以及事件属性赋值为null来进行事件的注销。
注册事件
- 属性注册方式又可分为在HTML元素内的事件属性赋值和通过JS指定元素对象的事件属性。
- 方法注册方式可通过addEventListener()或attachEvent()方法进行事件的注册。
在HTML元素内的事件属性赋值
说明:在HTML页面中,设置元素属性为一个函数。
语法:<button onlick="sayHello()">点击</button>
注意:事件属性是以"on"开头,后面跟着事件名称。如:onclick、onload。
function sayHello() {
console.log('hello')
}
----
<button onclick="sayHello()">点击</button>
通过JS指定元素对象的事件属性
说明:通过JS获取元素的对象,设置其事件属性为一个事件处理程序。
语法:EventTarget.onEventName=function(e){};
注意:事件属性是以"on"开头,后面跟着事件名称。如:onclick、onload。
唯一性:属性注册具有唯一性;同一个事件,最后注册的处理程序将会覆盖前面注册的处理程序。
示例1:事件属性注册的演示
// 注册body的click事件
document.body.onclick = function (e) {
alert(1);
};
示例2:事件属性注册的唯一性
document.body.onclick=function(e){
console.log(1);
}
// 会覆盖前面注册的事件处理程序
document.body.onclick=function(e){
console.log(2);
}
document.body.click(); // => 2 :只输出后面属性注册的
addEventListener()方法注册事件
说明:在JS中,window、document、HtmlElement等对象可以通过addEventListener()方法注册事件的处理程序。
语法:EventTarget.addEventListener(eventName, eventHandler, |useCapture )
参数:
①eventName {string} :所要注册的事件名称,不区分大小写。此名称不需要像注册事件属性那样前缀加上"on"。如注册鼠标点击事件,写为click。
②eventHandler {function | function Object} :函数或者函数对象。事件触发时所需要执行的函数;当使用函数对象多次注册同一事件时,只当注册一遍。
③useCapture {boolean} 可选 :是否处于捕获阶段,默认为false。
多次注册:addEventListener()方法能为同一个对象的同一事件注册多次。当发生此事件时,注册的处理事件程序将按照注册先后顺序执行。
注意:
①IE9之前的IE的不支持此方法,可使用attachEvent()代替。
②若使用相同的事件处理程序对象多次注册在同一个事件上,只算注册一次。
示例1:多次注册同一事件,按注册顺序执行,先输出1,再输出2
document.body.addEventListener('click',function(e){
console.log('1');
});
document.body.addEventListener('click',function(e){
console.log('2');
});
document.body.click(); // => 1,2
示例2:使用函数对象多次注册同一事件:只当注册一次
function sayHello(){
console.log('hello');
}
document.body.addEventListener('click',sayHello);
// 使用处理程序多次注册同一事件,只当注册一次
document.body.addEventListener('click',sayHello);
document.body.click(); // => hello :只输出一遍
attachEvent()方法
IE相关,这里不扩展。
JQuery中的事件注册方式(工作中常用)
JQuery中的事件注册方式对多浏览器的差异性进行了解决:判断元素是否含有addEventListener()或者attachEvent()方法。
function add(element,type, eventHandle){
if (element.addEventListener) {
element.addEventListener(type, eventHandle, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, eventHandle);
}
}
注销事件
可以注册元素的事件, 相应的可以也注销元素的事件。
JS中,可调用removeEventListener()[对应于addEventListener()] 和detachEvent()[对应于attachEvent()]来注销元素的某个事件指定的处理程序,也可以给事件属性赋值null来注销此事件的所有绑定。
removeEventListener(eventName, function Object)
说明:注销通过addEventListener()注册的事件处理程序。
语法:EventTarget.removeEventListener(eventName, eventHandlerObj)
参数:
①eventName {string} :所要注销的事件名称,不区分大小写。此名称不需要像注册事件属性那样前缀加上"on"。如注册鼠标点击事件,写为click。
②eventHandlerObj {function Object} :函数对象。传入一个函数体是没有效果的。
示例1:通过addEventListener()注销事件
function sayHello(e) {
console.log('1');
}
// 注册body click事件
document.body.addEventListener('click', sayHello);
// 注销body click事件的sayHello函数
document.body.removeEventListener('click',sayHello);
document.body.click(); // 触发click事件,不输出任何结果
示例2:若第二个参数为函数体,将不会注销
function sayHello(e) {
console.log('1');
}
// 注册body click事件
document.body.addEventListener('click', sayHello);
// 第二个参数为函数体,虽然跟sayHello函数的内容一样,但不会注销
document.body.removeEventListener('click', function(e) {
console.log('1');
});
document.body.click(); // => 1 :输出结果为1,并没有注销成功
detachEvent(eventName, function Object)
说明:注销通过attachEvent()注册的事件处理程序。
语法:EventTarget.detachEvent(eventName, eventHandlerObj)
参数:
①eventName {string} :所要注销的事件名称,区分大小写。这里的名称跟事件属性一样,以"on"开头,后面跟着事件名称。如:onclick、onload。
②eventHandlerObj {function Object} ::函数对象。传入一个函数体是没有效果的。
取消事件
给对象的事件属性赋值为null,可取消此事件的所有注册过的处理事件程序。
注意是所有的。而前面介绍的是取消特定的处理函数。
Event事件流与事件委托(类比iOS中的事件响应过程)
事件流
事件流的三个阶段(和iOS非常相似)
2级DOM事件规范制定了事件流的三个阶段:捕获阶段、目标阶段和冒泡阶段:
捕获阶段(Capture Phase):事件从最外层的window对象到目标节点的父节点依次触发的阶段。(从外到内)
目标阶段(Target Phase):事件在目标节点上触发时的阶段。
冒泡阶段(Bubbing Phase):事件从目标节点的父节点到最外层的window对象依次触发的阶段。(从内到外)
addEventListener()注册事件流的阶段
元素对象通过addEventListener()注册事件时,此方法的的第三个参数可设置本次注册是捕获阶段还是冒泡阶段。
- addEventListener()方法说明
语法:EventTarget.addEventListener(eventName, eventHandler [, useCapture] )
参数:
①eventName {string} :所要注册的事件名称,不区分大小写。此名称不需要像注册事件属性那样在前缀加上"on"。如注册鼠标点击事件,写为click。
②eventHandler {function | function Object} :函数或者函数对象。事件触发时所需要执行的函数;当使用函数对象多次注册同一事件时,只当注册一遍。
③useCapture {boolean} 可选 :是否处于捕获阶段,默认为false。
|-true:当前注册的事件为捕获阶段。
|-false:当前注册的事件不为捕获阶段,为冒泡阶段。
实例:
function clickHandle(e){
console.log("事件阶段:"+e.eventPhase+';target:'+e.target+';currentTarget:'+e.currentTarget)
}
window.addEventListener('click',clickHandle,false);
window.addEventListener('click',clickHandle,true);
document.addEventListener('click',clickHandle,false);
document.addEventListener('click',clickHandle,true);
document.documentElement.addEventListener('click',clickHandle,false);
document.documentElement.addEventListener('click',clickHandle,true);
document.body.addEventListener('click',clickHandle,false);
document.body.addEventListener('click',clickHandle,true);
document.getElementById('div').addEventListener('click',clickHandle,false);
document.getElementById('div').addEventListener('click',clickHandle,true);
document.getElementById('btn').addEventListener('click',clickHandle,false);
document.getElementById('btn').addEventListener('click',clickHandle,true);
阻止事件流的传播
Event 事件对象的stopPropagation()、stopImmediatePropagation()方法可阻止事件流的后续传播。
注:stopImmediatePropagation()方法除了阻止事件流传播还会阻止当前事件在此元素的后续事件处理程序。
在不同阶段阻止会立即阻止之后的操作,而不会影响之前的操作。
事件委托(Event Delegate)
简单来说事件委托就是父元素监听子元素的冒泡事件。
-
详细解释:
- HTML元素含有嵌套关系,并且事件流含有冒泡阶段。子元素的触发事件会冒泡到父元素的相同事件上。
- 一般情况只需给子元素注册特定的事件处理程序即可,但当子元素过多或频繁的进行增减操作怎么办?
- 比如一个ul包含了几十个li元素,对每个li元素进行单独的事件注册会影响性能。而现只要在父元素注册事件监听器,等待li事件触发后的冒泡阶段即可。
实例
Div容器包含了多个li子元素,在Div容器注册事件委托。
HTML代码:
<div id="div">
<ul id="ul" >
<li data-key="北京">北京</li>
<li data-key="上海">上海</li>
<li data-key="杭州">杭州</li>
</ul>
</div>
JS代码:
document.getElementById('div').addEventListener('click',function(e){
var value=e.target.attributes['data-key'].value; // 获取目标阶段元素的'data-key'属性的值
console.log(value);
});
JQuery的事件委托
在JQuery中,父元素可调用delegate()、on()作为事件委托使用。
delegate()
语法:$('父元素').delegate( selector [, eventType] [, eventData], handler )
参数:
①selector {string} :子元素的选择器、
②eventType {eventType} 可选 :触发的事件类型。如:click。
③eventData {object} 可选 :触发事件时event.data指向的值。
④handler {function} :事件注册的处理程序。
例子:
$('#div').delegate('li', 'click', function() {
var v = $(this).data('key');
console.log(v);
});
on()
说明:JQuery1.7版本开始时,推荐on()代替delegate()方法。
语法:$('元素').on( events [, selector ] [, data ], handler )
参数:
①events {string} :一个或多个事件名称。
②selector {string} 可选 :子元素选择器。若无此值,表示元素注册本身的事件。若含有此值,表示只有子元素的事件触发,才会触发注册的事件。
③data {object} 可选 :触发事件时的event.data指向的值。
④handler {function} :事件注册的处理程序。
$('#div').on('click','li',function(e) {
var v = $(this).data('key');
console.log(v);
});
Event模拟事件操作
具体的查看相关API
触发元素的事件可以直接调用事件方法(如:click()触发元素的click事件)。为何还要单独的模拟触发呢?
与直接触发相比,模拟事件包含以下特点:
①模拟特定场景:如触发click事件,可同时模拟是否按下Ctrl、Alt等按键。
②可触发自定义事件。
自定义事件
模拟事件支持模拟触发自定义事件。
例子:
<button id="a-btn">A按钮</button>
<button id="b-btn">B按钮</button>
JS:
// 按钮A
document.getElementById('a-btn').onclick=function(e){
var customEvent=document.createEvent('CustomEvent'); // 1.创建一个自定义事件类型
customEvent.initCustomEvent('build'); // 2.初始化一个build事件
document.getElementById('b-btn').dispatchEvent(customEvent); // 3.派发(触发)
};
// 按钮B注册一个自定义事件
document.getElementById('b-btn').addEventListener('build',function(){
console.log('b-btn build');
});
老版
通过document.createEvent()方法创建各事件类型对象。
①通过document.createEvent(eventType)方法创建一个event对象。
②调用event.initEvent()方法进行事件初始化。注意:不同的事件类型对象,其初始化的方法名称也不通;比如MouseEvent的为event.initMouseEvent()。
③调用元素对象的dispatchEvent(event对象)方法进行派发。
实例
模拟鼠标点击
HTML:
<button id="a-btn">A按钮</button>
<button id="b-btn">B按钮</button>
JS:
// 按钮A点击时,模拟触发按钮B的点击事件
document.getElementById('a-btn').onclick=function(e){
var clickEvent=document.createEvent('MouseEvent'); // 1.创建一个鼠标事件类型
clickEvent.initMouseEvent('click',false,false,window,0,0,0,0,0,false,false,false,false,0,null); // 2.初始化一个click事件
document.getElementById('b-btn').dispatchEvent(clickEvent); // 3.派发(触发)
};
// 按钮B
document.getElementById('b-btn').onclick=function(e){
console.log('b');
};
新版
通过各事件的构造函数创建事件类型对象。
①通过各事件类型的构造函数创建一个event对象。
②调用元素对象的dispatchEvent(event对象)方法进行派发。
实例
- 模拟鼠标点击:模拟鼠标点击,按钮A和B都注册了各自的点击事件,点击按钮A时,模拟触发按钮B的点击事件并且模拟alt按键按下。
HTML:
<button id="a-btn">A按钮</button>
<button id="b-btn">B按钮</button>
JS:
// 按钮A点击时,模拟触发按钮B的点击事件
document.getElementById('a-btn').onclick=function(e){
var clickEvent=new MouseEvent('click',{
altKey:true // 模拟alt键按下
});
document.getElementById('b-btn').dispatchEvent(clickEvent); // 派发
};
// 按钮B
document.getElementById('b-btn').onclick=function(e){
console.log('按钮b点击事件触发;alt案件是否按下:'+e.altKey);
};
- 自定义事件:模拟事件支持模拟触发自定义事件。
HTML:
<button id="a-btn">A按钮</button>
<button id="b-btn">B按钮</button>
JS:
// 按钮A
document.getElementById('a-btn').onclick=function(e){
var customEvent = new CustomEvent('build');
document.getElementById('b-btn').dispatchEvent(customEvent); // 派发
};
// 按钮B注册一个自定义事件
document.getElementById('b-btn').addEventListener('build',function(){
console.log('b-btn build');
});