澳门新葡萄京官网注册事件模型

文书档案布局

<h1 id=”5″>DOM</h1>

事件是一种异步编制程序的得以达成形式,本质上是前后相继各类组成都部队分之间的通讯。DOM匡助大气的事件,本节介绍DOM的事件编制程序。

对二个图纸加多该意义,首先,大家要求三个存有宽高的器皿。DOM
构造特别轻易。

<h2 id=”5.1″>DOM节点</h2>

EventTarget接口

DOM的风云操作(监听和接触),都定义在EventTarget接口。Element节点、document节点和window目的,都配置了那些接口。别的,XMLHttpRequestAudioNodeAudioContext等浏览器内置对象,也配备了那个接口。

该接口就是七个艺术。

  • addEventListener:绑定事件的监听函数
  • removeEventListener:移除事件的监听函数
  • dispatchEvent:触发事件
divclass=containerimgclass=tilt-effectsrc=

DOM的概念

DOM是文书档案对象模型(Document Object
Model)的简称,它的主导寻思是把构造化文书档案(举个例子HTML和XML)深入分析成一层层的节点,再由那几个节点组成三个树状布局(DOM
Tree)。全数的节点和终极的树状布局,皆有行业内部的对外接口,以达到使用编制程序语言操作文书档案的指标(比如增加和删除内容)。所以,DOM能够驾驭成文书档案(HTML文书档案、XML文书档案和SVG文书档案)的编制程序接口。

DOM有和煦的国际标准,最近的通用版本是DOM
3,下一代版本DOM
4正在制定中。本章介绍的就是JavaScript对DOM标准的兑现和用法。

严刻地说,DOM不归属JavaScript,不过操作DOM是JavaScript最广泛的任务,而JavaScript也是最常用于DOM操作的言语。所以,DOM往往放在JavaScript里面介绍。

addEventListener()

addEventListener形式用于在当下节点或对象上,定义三个特定事件的监听函数。

// 使用格式
target.addEventListener(type, listener[, useCapture]);

// 实例
window.addEventListener('load', function () {...}, false);
request.addEventListener('readystatechange', function () {...}, false);

addEventListener主意选用四个参数。

  • type:事件名称,大小写敏感。
  • listener:监听函数。事件时有爆发时,会调用该监听函数。
  • useCapture:布尔值,表示监听函数是不是在捕获阶段(capture)触发(参见后文《事件的流传》部分),默以为false(监听函数只在冒泡阶段被触发)。老式浏览器规定该参数必写,较新本子的浏览器允许该参数可选。为了保险非凡,提议总是写上该参数。

上面是一个例证。

function hello() {
  console.log('Hello world');
}

var button = document.getElementById('btn');
button.addEventListener('click', hello, false);

地点代码中,addEventListener方法为button要秋季点,绑定click事件的监听函数hello,该函数只在冒泡阶段触发。

addEventListener方式可以为当下指标的同四个事件,加多两个监听函数。那几个函数根据增多顺序触发,即先增多先触发。要是为同三个风云频仍加多同二个监听函数,该函数只会实行一遍,多余的增进将自行被删除(不必选拔removeEventListener办法手动去除)。

function hello() {
  console.log('Hello world');
}

document.addEventListener('click', hello, false);
document.addEventListener('click', hello, false);

执行上面代码,点击文书档案只会输出一行Hello world

借使期望向监听函数字传送递参数,能够用无名氏函数包装一下监听函数。

function print(x) {
  console.log(x);
}

var el = document.getElementById('div1');
el.addEventListener('click', function () { print('Hello'); }, false);

上边代码通过佚名函数,向监听函数print传送了多个参数。

下边这段布局经过脚本管理以往,会被替换来下边包车型大巴布局:

节点的概念

DOM的小小组成单位叫做节点(node),三个文书档案的树形布局(DOM树),正是由种种不一样档案的次序的节点组成。

对此HTML文书档案,节点首要有以下六连串型:Document节点、DocumentType节点、Element节点、Attribute节点、Text节点和DocumentFragment节点。

节点 名称 含义
Document 文档节点 整个文档(window.document)
DocumentType 文档类型节点 文档的类型(比如<!DOCTYPE html>)
Element 元素节点 HTML元素(比如<body>、<a>等)
Attribute 属性节点 HTML元素的属性(比如class="right")
Text 文本节点 HTML文档中出现的文本
DocumentFragment 文档碎片节点 文档的片段

浏览器原生提供一个Node对象,上表全数品种的节点都以Node对象派生出来的。约等于说,它们都一而再了Node的习性和方式。

removeEventListener()

removeEventListener主意用来移除addEventListener措施增多的风浪监听函数。

div.addEventListener('click', listener, false);
div.removeEventListener('click', listener, false);

removeEventListener方法的参数,与addEventListener主意别无二样。它的首先个参数“事件类型”,大小写敏感。

注意,removeEventListener方法移除的监听函数,必得与相应的addEventListener措施的参数别无二致,何况必得在同多少个要商节点,不然无效。

divclass=containerdivclass=tiltdivclass=tilt__backstyle=background-image:url();/divdivclass=tilt__frontstyle=opacity:0.7;-webkit-transform:perspective(1000px)translate3d(0px,0px,0px)rotate3d(1,1,1,0deg);transform:perspective(1000px)translate3d(0px,0px,0px)rotate3d(1,1,1,0deg);background-image:url();/divdivclass=tilt__frontstyle=opacity:0.7;-webkit-transform:perspective(1000px)translate3d(0px,0px,0px)rotate3d(1,1,1,0deg);transform:perspective(1000px)translate3d(0px,0px,0px)rotate3d(1,1,1,0deg);background-image:url();/div/div/div

Node节点的习性

dispatchEvent()

dispatchEvent措施在现阶段节点上接触钦点事件,进而触发监听函数的施行。该办法再次回到多个布尔值,只要有二个监听函数调用了Event.preventDefault(),则重临值为false,否则为true

target.dispatchEvent(event)

dispatchEvent艺术的参数是三个Event对象的实例。

para.addEventListener('click', hello, false);
var event = new Event('click');
para.dispatchEvent(event);

地点代码在当前节点触发了click事件。

如果dispatchEvent艺术的参数为空,可能不是三个灵光的平地风波指标,将报错。

下边代码依照dispatchEvent艺术的重返值,决断事件是或不是被吊销了。

var canceled = !cb.dispatchEvent(event);
  if (canceled) {
    console.log('事件取消');
  } else {
    console.log('事件未取消');
  }
}

本子剖判

nodeName,nodeType

nodeName品质重返节点的称号,nodeType品质再次回到节点类型的常数值。具体的重临值,可查阅下方的报表。

类型 nodeName nodeType
DOCUMENT_NODE #document 9
ELEMENT_NODE 大写的HTML元素名 1
ATTRIBUTE_NODE 等同于Attr.name 2
TEXT_NODE #text 3
DOCUMENT_FRAGMENT_NODE #document-fragment 11
DOCUMENT_TYPE_NODE 等同于DocumentType.name 10

document节点为例,它的nodeName属性等于#documentnodeType个性等于9。

document.nodeName // "#document"
document.nodeType // 9

习感觉常来讲,使用nodeType属性分明一个节点的项目,相比便利。

document.querySelector('a').nodeType === 1
// true

document.querySelector('a').nodeType === Node.ELEMENT_NODE
// true

地点三种写法是等价的。

监听函数

监听函数(listener)是事件发生时,程序所要实行的函数。它是事件驱动编制程序格局的基本点编制程序格局。

DOM提供三种办法,能够用来为事件绑定监听函数。

大家采取了filtfx.js那些插件对上面包车型客车图片实行管理,
来达成偏斜效果。小编在原先的代码中参加了部分讲授,来协助我们理解。上面大家对该插件的为主代码进行剖析。

ownerDocument,nextSibling,previousSibling,parentNode,parentElement

以下属性再次回到当前节点的相关节点。

(1)ownerDocument

ownerDocument属性再次来到当前节点所在的顶层文档对象,即document对象。

var d = p.ownerDocument;
d === document // true

document对象自作者的ownerDocument属性,再次来到null。

(2)nextSibling

nextSibling属性再次回到紧跟在近年来节点后边的率先个同级节点。假使当前节点前面未有同级节点,则赶回null。注意,该属性还包含文件节点和评价节点。因而一旦当前节点后边有空格,该属性会重返一个文本节点,内容为空格。

var el = document.getElementById('div-01').firstChild;
var i = 1;

while (el) {
  console.log(i + '. ' + el.nodeName);
  el = el.nextSibling;
  i++;
}

上面代码遍历div-01节点的全部子节点。

(3)previousSibling

previousSibling属性重返当前节点前边的、间距近年来的一个同级节点。假使当前节点前边未有同级节点,则赶回null。

// html代码如下
// <a><b1 id="b1"/><b2 id="b2"/></a>

document.getElementById("b1").previousSibling // null
document.getElementById("b2").previousSibling.id // "b1"

对此眼下节点后边有空格,则previousSibling属性会重返二个内容为空格的文件节点。

(4)parentNode

parentNode脾性重回当前节点的父节点。对于叁个节点的话,它的父节点只大概是两种档案的次序:element节点、document节点和documentfragment节点。

下边代码是什么从父节点移除内定节点。

if (node.parentNode) {
  node.parentNode.removeChild(node);
}

对此document节点和documentfragment节点,它们的父节点都以null。此外,对于这些变化后还没有插入DOM树的节点,父节点也是null。

(5)parentElement

parentElement属性重回当前节点的父Element节点。借使当前节点未有父节点,或然父节点类型不是Element节点,则赶回null。

if (node.parentElement) {
  node.parentElement.style.color = "red";
}

下边代码设置内定节点的父Element节点的CSS属性。

在IE浏览器中,独有Element节点才有该属性,其余浏览器则是装有品类的节点都有该属性。

HTML标签的on-属性

HTML语言允许在要素标签的性质中,直接定义有些事件的监听代码。

<body onload="doSomething()">
<div onclick="console.log('触发事件')">

上面代码为body节点的load事件、div节点的click事件,钦点了监听函数。

使用这么些法子内定的监听函数,只会在冒泡阶段触发。

留意,使用这种办法时,on-天性的值是将会施行的代码,实际不是叁个函数。

<!-- 正确 -->
<body onload="doSomething()">

<!-- 错误 -->
<body onload="doSomething">

假使钦点的风浪发生,on-性子的值是面容传入JavaScript引擎试行。因而一旦要推行函数,不要忘记记加上一对圆括号。

除此以外,Element元商节点的setAttribute办法,其实设置的也是这种意义。

el.setAttribute('onclick', 'doSomething()');
functionTiltFx(el,options){this.el=el;this.options=extend({},this.options);extend(this.options,options);this._init();this._initEvents();}

textContent,nodeValue

以下属性再次回到当前节点的剧情。

(1)textContent

textContent属性重临当前节点和它的保有后代节点的文本内容。

// HTML代码为
// <div id="divA">This is some text</div>

document.getElementById("divA").textContent
// This is some text

地点代码的textContent属性,自动忽视当前节点内部的HTML标签,再次回到全部文件内容。

该属性是可读写的,设置该属性的值,会用二个新的公文节点,替换全数它原来的子节点。它还可能有多个功利,便是活动对HTML标签转义。那很符合用于客商提供的从头到尾的经过。

document.getElementById('foo').textContent = '<p>GoodBye!</p>';

上边代码在插入文本时,会将p标签解释为文本,即<p>,而不会作为标签管理。

对于Text节点和Comment节点,该属性的值与nodeValue属性相仿。对于别的连串的节点,该属性会将各类子节点的原委连接在一同回到,然则不富含Comment节点。如若叁个节点未有子节点,则赶回空字符串。

document节点和doctype节点的textContent属性为null。假设要读取整个文档的内容,能够应用document.documentElement.textContent

在IE浏览器,全体Element节点都有一个innerText属性。它与textContent属性基本相像,然则有几点分别。

  • innerText受CSS影响,textContent不受。比方,借使CSS法规隐敝(hidden)了某段文本,innerText就不会回去这段文本,textContent则依然再次回到。

  • innerText再次来到的文本,会过滤掉空格、换行和回车键,textContent则不会。

  • innerText属性不是DOM规范的一有的,Firefox浏览器如故从不布置这么些本性,而textContent是DOM标准的一片段。

(2)nodeValue

nodeValue属性再次回到或设置当前节点的值,格式为字符串。但是,该属性只对Text节点、Comment节点、XML文书档案的CDATA节点有效,其余品种的节点一律再次回到null。

就此,nodeValue属性日常只用于Text节点。对于那多少个重返null的节点,设置nodeValue属性是无用的。

Element节点的风浪性质

Element节点对象有事件性质,近似可以钦定监听函数。

window.onload = doSomething;

div.onclick = function(event){
  console.log('触发事件');
};

使用那几个法子钦命的监听函数,只会在冒泡阶段触发。

那是布局函数,即使我们的文书档案中,参加了地方的插件,那么插件会遍历文书档案中负有tilt-effetimg要素,来调用布局函数TiltFx()

childNodes,firstChild,lastChild

以下属性重临当前节点的子节点。

(1)childNodes

childNodes属性重临三个NodeList集结,成员满含方今节点的所有子节点。注意,除了HTML成分节点,该属性再次回到的还蕴涵Text节点和Comment节点。假设当前节点不满含任何子节点,则赶回二个空的NodeList集结。由于NodeList对象是五个动态集结,一旦子节点产生变化,立刻会反映在回去结果个中。

var ulElementChildNodes = document.querySelector('ul').childNodes;

(2)firstChild

firstChild脾气重返当前节点的首先个子节点,如若当前节点未有子节点,则赶回null

<p id="para-01">First span</p>

<script type="text/javascript">
  console.log(
    document.getElementById('para-01').firstChild.nodeName
  ) // "span"
</script>

地点代码中,p要素的首先体态节点是span元素。

注意,firstChild回到的除了HTML成分子节点,还大概是文本节点或评头论脚节点。

<p id="para-01">
  First span
</p>

<script type="text/javascript">
  console.log(
    document.getElementById('para-01').firstChild.nodeName
  ) // "#text"
</script>

地点代码中,p元素与span要素之间有空白字符,那招致firstChild回来的是文件节点。

(3)lastChild

lastChild属性重回当前节点的末段四个子节点,假诺当前节点没有子节点,则赶回null。

addEventListener方法

通过Element节点、document节点、window对象的addEventListener措施,也可以定义事件的监听函数。

window.addEventListener('load', doSomething, false);

addEventListener方法的详实介绍,参见本节EventTarget接口的一些。

在上头二种办法中,第一种“HTML标签的on-属性”,违反了HTML与JavaScript代码相分离的原则;第三种“Element节点的事件性质”的症结是,同四个事件只好定义三个监听函数,也正是说,假设定义五回onclick属性,后一次定义会覆盖前叁次。由此,这二种艺术都不引入应用,除非是为了程序的宽容难题,因为具备浏览器都协助那二种办法。

add伊芙ntListener是引进的钦赐监听函数的诀要。它犹如下优点:

  • 能够针对同三个事件,加多八个监听函数。

  • 能够钦点在哪个阶段(捕获阶段只怕冒泡阶段)触发回监听函数。

  • 除了DOM节点,仍是可以配备在windowXMLHttpRequest等指标方面,等于统一了全部JavaScript的监听函数接口。

functioninit(){//遍历所有拥有‘title-effect’类的img元素[].slice.call(document.querySelectorAll(img.tilt-effect)).forEach(function(img){newTiltFx(img,JSON.parse(img.getAttribute(data-tilt-options)));});}

baseURI

baseUEvoqueI属性重临八个字符串,由近日网页的商事、域名和各州的目录组成,表示这几天网页的相对路线。假设不可能取到这一个值,则赶回null。浏览器根据那几个性子,总计网页上的相对路线的ULANDL。该属性为只读。

平日状态下,该属性由近些日子网址的ULANDL(即window.location属性)决定,然而足以应用HTML的<base>标签,更动该属性的值。

<base href="http://www.example.com/page.html">
<base target="_blank" href="http://www.example.com/page.html">

该属性不仅仅document对象有(document.baseURI),成分节点也会有(element.baseURI)。常常情状下,它们的值是同等的。

this对象的针对

骨子里编制程序中,监听函数内部的this目的,日常要求针对触发事件的老大Element节点。

addEventListener艺术钦定的监听函数,内部的this目的总是指向触发事件的不得了节点。

// HTML代码为
// <p id="para">Hello</p>

var id = 'doc';
var para = document.getElementById('para');

function hello(){
  console.log(this.id);
}

para.addEventListener('click', hello, false);

实行上面代码,点击<p>节点会输出para。那是因为监听函数被“拷贝”成了节点的壹脾质量,所以this指向节点指标。使用上边的写法,会看得更清楚。

para.onclick = hello;

万一将监听函数布置在Element节点的on-质量上边,this不会指向触发事件的成分节点。

<p id="para" onclick="hello()">Hello</p>
<!-- 或者使用JavaScript代码  -->
<script>
  pElement.setAttribute('onclick', 'hello()');
</script>

实行上边代码,点击<p>节点会输出doc。那是因为这里只是调用hello函数,而hello函数实际是在大局作用域施行,相当于上面包车型地铁代码。

para.onclick = function () {
  hello();
}

一种减轻措施是,不引进函数功能域,直接在on-质量写入所要施行的代码。因为on-属性是在脚下节点上实行的。

<p id="para" onclick="console.log(id)">Hello</p>
<!-- 或者 -->
<p id="para" onclick="console.log(this.id)">Hello</p>

上边两行,最后输出的都是para

小结一下,以下写法的this指标都指向Element节点。

// JavaScript代码
element.onclick = print
element.addEventListener('click', print, false)
element.onclick = function () {console.log(this.id);}

// HTML代码
<element onclick="console.log(this.id)">

以下写法的this指标,都照准全局对象。

// JavaScript代码
element.onclick = function (){ doSomething() };
element.setAttribute('onclick', 'doSomething()');

// HTML代码
<element onclick="doSomething()">

TiltFx()富有三个原型属性,多少个原型方法。原型属性配置了有的私下认可的参数用于调用:

Node节点的办法

事件的传遍

/***默认参数*/TiltFx.prototype.options={extraImgs:2,//额外的辅助图片数量opacity:0.7,bgfixed:true,//底图是否固定movement:{//这是一些用于移动的参数perspective:1000,translateX:-10,translateY:-10,translateZ:20,rotateX:2,rotateY:2,rotateZ:0}}

appendChild(),hasChildNodes()

以下办法与子节点相关。

(1)appendChild()

appendChild方法选用三个节点指标作为参数,将其看做最后一个子节点,插入当前节点。

var p = document.createElement("p");
document.body.appendChild(p);

一旦参数节点是文书档案中现有的其他节点,appendChild方法会将其从原先的岗位,移动到新职责。

hasChildNodes方法再次来到三个布尔值,表示近些日子节点是还是不是有子节点。

var foo = document.getElementById("foo");

if ( foo.hasChildNodes() ) {
  foo.removeChild( foo.childNodes[0] );
}

地点代码表示,若是foo节点有子节点,就移除第一身长节点。

(2)hasChildNodes()

hasChildNodes方法结合firstChild属性和nextSibling属性,能够遍历当前节点的全体后代节点。

function DOMComb (oParent, oCallback) {
  if (oParent.hasChildNodes()) {
    for (var oNode = oParent.firstChild; oNode; oNode = oNode.nextSibling) {
      DOMComb(oNode, oCallback);
    }
  }
  oCallback.call(oParent);
}

上边代码的DOMComb函数的首先个参数是某些钦定的节点,第贰个参数是回调函数。那么些回调函数会相继成效于钦命节点,以致内定节点的有着后代节点。

function printContent () {
  if (this.nodeValue) {
    console.log(this.nodeValue);
  }
}

DOMComb(document.body, printContent);

传播的八个等第

当四个平地风波发生之后,它会在不一致的DOM节点之间传遍(propagation)。这种流传分成四个阶段:

  • 先是品级:从window对象传导到对象节点,称为“捕获阶段”(capture
    phase)。

  • 其次品级:在指标节点上接触,称为“目的阶段”(target phase)。

  • 其三等级:从指标节点传导回window对象,称为“冒泡阶段”(bubbling
    phase)。

这种三品级的传播模型,会使得一个事变在四个节点上接触。比如,如果点击<div>里面嵌套三个<p>节点。

<div>
  <p>Click Me</p>
</div>

若果对那七个节点的click事件都设定监听函数,则click事件会被触发伍遍。

var phases = {
  1: 'capture',
  2: 'target',
  3: 'bubble'
};

var div = document.querySelector('div');
var p = document.querySelector('p');

div.addEventListener('click', callback, true);
p.addEventListener('click', callback, true);
div.addEventListener('click', callback, false);
p.addEventListener('click', callback, false);

function callback(event) {
  var tag = event.currentTarget.tagName;
  var phase = phases[event.eventPhase];
  console.log("Tag: '" + tag + "'. EventPhase: '" + phase + "'");
}

// 点击以后的结果
// Tag: 'DIV'. EventPhase: 'capture'
// Tag: 'P'. EventPhase: 'target'
// Tag: 'P'. EventPhase: 'target'
// Tag: 'DIV'. EventPhase: 'bubble'

上边代码表示,click事件被触发了八次:<p>节点的抓获阶段和冒泡阶段各1次,<div>节点的抓获阶段和冒泡阶段各1次。

  1. 破获阶段:事件从<div><p>传播时,触发<div>click事件;
  2. 对象阶段:事件从<div>到达<p>时,触发<p>click事件;
  3. 对象阶段:事件离开<p>时,触发<p>click事件;
  4. 冒泡阶段:事件从<p>传回<div>时,再度接触<div>click事件。

注意,用户点击网页的时候,浏览器总是假定click事件的靶子节点,就是点击地方的嵌套最深的老大节点(嵌套在<div>节点的<p>节点)。所以,<p>节点的捕获阶段和冒泡阶段,都展会示为target阶段。

事件传播的最上层对象是window,接着依次是documenthtmldocument.documentElement)和bodydocument.dody)。相当于说,假如<body>要素中有一个<div>要素,点击该因素。事件的散播顺序,在捕获阶段依次为windowdocumenthtmlbodydiv,在冒泡阶段依次为divbodyhtmldocumentwindow

先是个原型方法是_init(),用于开首化DOM结点,生成大家的目的DOM结点:

cloneNode(),insertBefore(),removeChild(),replaceChild()

下边方法与节点操作有关。

(1)cloneNode()

cloneNode方法用于克隆八个节点。它采用八个布尔值作为参数,表示是还是不是还要克隆子节点,默许是false,即不克隆子节点。

var cloneUL = document.querySelector('ul').cloneNode(true);

急需留意的是,克隆一个节点,会拷贝该节点的装有属性,不过会丧失add伊芙ntListener方法和on-属性(即node.onclick = fn),加多在此个节点上的轩然大波回调函数。

克隆三个节点之后,DOM树有异常的大或者现身七个有同等ID属性(即id="xxx")的HTML成分,此时应该改过此中二个HTML成分的ID属性。

(2)insertBefore()

insertBefore方法用于将某些节点插入当前节点的钦命地点。它肩负四个参数,第三个参数是所要插入的节点,第一个参数是时下节点的多少个子节点,新的节点将插在此个节点的前边。该措施重返被插入的新节点。

var text1 = document.createTextNode('1');
var li = document.createElement('li');
li.appendChild(text1);

var ul = document.querySelector('ul');
ul.insertBefore(li,ul.firstChild);

上边代码在ul节点的最前方,插入二个新建的li节点。

假使insertBefore方法的第四个参数为null,则新节点将插在当下节点的最终地点,即成为最终二个子节点。

将新节点插在近期节点的最前边(即形成第一体态节点),能够应用当前节点的firstChild属性。

parentElement.insertBefore(newElement, parentElement.firstChild);

上边代码中,即使当前节点没有任何子节点,parentElement.firstChild会重回null,则新节点会插在日前节点的末梢,等于是第一身长节点。

鉴于不设有insertAfter方法,假使要插在时下节点的有个别子节点前面,能够用insertBefore方法结合nextSibling属性模拟。

parentDiv.insertBefore(s1, s2.nextSibling);

上面代码能够将s1节点,插在s2节点的前边。假使s2是当下节点的尾声叁个子节点,则s2.nextSibling再次来到null,那时候s1节点会插在现阶段节点的末尾,产生眼下节点的末尾二个子节点,等于紧跟在s2的背后。

(3)removeChild()

removeChild方法选取二个子节点作为参数,用于从日前节点移除该节点。它回到被移除的节点。

var divA = document.getElementById('A');
divA.parentNode.removeChild(divA);

上边代码是如何移除几个钦命节点。

下边是何许移除当前节点的全数子节点。

var element = document.getElementById("top");
while (element.firstChild) {
  element.removeChild(element.firstChild);
}

被移除的节点依旧留存于内部存款和储蓄器之中,可是不再是DOM的一有的。所以,四个节点移除未来,依旧得以利用它,比方插入到另一个节点。

(4)replaceChild()

replaceChild方法用于将二个新的节点,替换当前节点的某贰个子节点。它接收五个参数,第三个参数是用来替换的新节点,第一个参数就要被替换走的子节点。它回到被交换走的分外节点。

replacedNode = parentNode.replaceChild(newChild, oldChild);

下边是二个例证。

var divA = document.getElementById('A');
var newSpan = document.createElement('span');
newSpan.textContent = 'Hello World!';
divA.parentNode.replaceChild(newSpan,divA);

上边代码是哪些替换钦点节点。

事件的代理

出于事件会在冒泡阶段发展传播到父节点,因而得以把手节点的监听函数定义在父节点上,由父节点的监听函数统一管理多少个子元素的风浪。这种措施叫做事件的代办(delegation)。

var ul = document.querySelector('ul');

ul.addEventListener('click', function(event) {
  if (event.target.tagName.toLowerCase() === 'li') {
    // some code
  }
});

地点代码的click事件的监听函数定义在<ul>节点,然而实际,它管理的是子节点<li>click事件。那样做的功利是,只要定义三个监听函数,就能够管理多个子节点的平地风波,何况今后再增加子节点,监听函数依然有效。

若是希望事件到有些节点停止,不再传播,可以运用事件指标的stopPropagation方法。

p.addEventListener('click', function(event) {
  event.stopPropagation();
});

动用方面包车型客车代码以往,click事件在冒泡阶段达到<p>节点今后,就不再发展(父节点的方向)传播了。

但是,stopPropagation方法只会阻碍当前监听函数的扩散,不会堵住<p>节点上的别样click事件的监听函数。借使想要不再触发那么些监听函数,能够行使stopImmediatePropagation方法。

p.addEventListener('click', function(event) {
 event.stopImmediatePropagation();
});

p.addEventListener('click', function(event) {
 // 不会被触发
});
TiltFx.prototype._init=function(){this.tiltWrapper=document.createElement(div);this.tiltWrapper.className=tilt;//mainimageelement.this.tiltImgBack=document.createElement(div);this.tiltImgBack.className=tilt__back;this.tiltImgBack.style.backgroundImage=url(+this.el.src+);this.tiltWrapper.appendChild(this.tiltImgBack);//imageelementslimit.if(this.options.extraImgs1){this.options.extraImgs=1;}elseif(this.options.extraImgs5){this.options.extraImgs=5;}if(!this.options.movement.perspective){this.options.movement.perspective=0;}//addtheextraimageelements.this.imgElems=[];for(vari=0;ithis.options.extraImgs;++i){varel=document.createElement(div);el.className=tilt__front;el.style.backgroundImage=url(+this.el.src+);el.style.opacity=this.options.opacity;this.tiltWrapper.appendChild(el);this.imgElems.push(el);}if(!this.options.bgfixed){this.imgElems.push(this.tiltImgBack);++this.options.extraImgs;}//addittotheDOMandremoveoriginalimgelement.this.el.parentNode.insertBefore(this.tiltWrapper,this.el);this.el.parentNode.removeChild(this.el);//tiltWrapperproperties:width/height/left/topthis.view={width:this.tiltWrapper.offsetWidth,height:this.tiltWrapper.offsetHeight};};

contains(),compareDocumentPosition(),isEqualNode()

上边方法用于节点的相互影响相比较。

(1)contains()

contains方法接收一个节点作为参数,重临叁个布尔值,表示参数节点是还是不是为近日节点的后代节点。

document.body.contains(node)

地方代码检查有个别节点,是或不是包罗在近期文档之中。

小心,如若将如今节点传入contains方法,会重返true。即便从意义上说,三个节点不应有包括笔者。

nodeA.contains(nodeA) // true

(2)compareDocumentPosition()

compareDocumentPosition方法的用法,与contains方法别无二致,重返三个7个比特位的二进制值,表示参数节点与当下节点的涉嫌。

二进制值 数值 含义
000000 0 两个节点相同
000001 1 两个节点不在同一个文档(即有一个节点不在当前文档)
000010 2 参数节点在当前节点的前面
000100 4 参数节点在当前节点的后面
001000 8 参数节点包含当前节点
010000 16 当前节点包含参数节点
100000 32 浏览器的私有用途
// HTML代码为
// <div id="writeroot">
//   <form>
//     <input id="test" />
//   </form>
// </div>

var x = document.getElementById('writeroot');
var y = document.getElementById('test');

x.compareDocumentPosition(y) // 20
y.compareDocumentPosition(x) // 10

地点代码中,节点x满含节点y,並且节点y在节点x的前边,所以率先个compareDocumentPosition方法重临20(010100),第1个compareDocumentPosition方法再次来到10(0010010)。

出于compareDocumentPosition重回值的意思,定义在每叁个比特位上,所以只要要反省某一种特定的意义,就须要使用比特位运算符。

var head = document.head;
var body = document.body;
if (head.compareDocumentPosition(body) & 4) {
  console.log("文档结构正确");
} else {
  console.log("<head> 不能在 <body> 前面");
}

上面代码中,compareDocumentPosition的重返值与4(又称掩码)进行与运算(&),得到一个布尔值,表示head是或不是在body前边。

在这里个办法的基础上,能够配备一些一定的函数,检查节点的职分。

Node.prototype.before = function (arg) {
  return !!(this.compareDocumentPosition(arg) & 2)
}

nodeA.before(nodeB)

上边代码在Node对象上配备了三个before方法,再次来到二个布尔值,表示参数节点是或不是在前段时间节点的跟前。

(3)isEqualNode()

isEqualNode方法再次来到一个布尔值,用于检查七个节点是或不是等于。所谓相等的节点,指的是多个节点的种类相符、属性相仿、子节点相似。

var targetEl = document.getElementById("targetEl");
var firstDiv = document.getElementsByTagName("div")[0];

targetEl.isEqualNode(firstDiv)

Event对象

事件时有爆发以往,会变卦三个平地风波目的,作为参数字传送给监听函数。浏览器原生提供二个Event指标,全部的风云都以其一指标的实例,可能说世襲了Event.prototype对象。

Event对象自小编就是三个布局函数,能够用来生成新的实例。

event = new Event(typeArg, eventInit);

Event布局函数选取五个参数。第三个参数是字符串,表示事件的称呼;第三个参数是八个指标,表示事件指标的安插。该参数能够有以下六个天性。

  • bubbles:布尔值,可选,默认为false,表示事件目标是还是不是冒泡。
  • cancelable:布尔值,可选,默认为false,表示事件是不是能够被打消。

var ev = new Event(
  'look',
  {
    'bubbles': true,
    'cancelable': false
  }
);
document.dispatchEvent(ev);

上面代码新建几个look事件实例,然后接纳dispatchEvent方法触发该事件。

IE8及以下版本,事件目的不作为参数字传送递,而是通过window对象的event天性读取,并且事件目的的target质量叫做srcElement属性。所以,从前获得事件音讯,往往要写成下边那样。

function myEventHandler(event) {
  var actualEvent = event || window.event;
  var actualTarget = actualEvent.target || actualEvent.srcElement;
  // ...
}

地点的代码只是为了印证以前的前后相继为啥这么写,在新代码中,那样的写法不应有再用了。

除此以外四个原型格局是用以监听鼠标事件等等的:

normalize()

normailize方法用于清理当前节点内部的持有Text节点。它会去除空的公文节点,而且将毗邻的文件节点合并成贰个。

var wrapper = document.createElement("div");

wrapper.appendChild(document.createTextNode("Part 1 "));
wrapper.appendChild(document.createTextNode("Part 2 "));

wrapper.childNodes.length // 2

wrapper.normalize();

wrapper.childNodes.length // 1

上边代码应用normalize方法从前,wrapper节点有八个Text子节点。使用normalize方法之后,八个Text子节点被联合成叁个。

该方法是Text.splitText的逆方法,能够查看《Text节点》章节,领悟越来越多内容。

event.bubbles,event.eventPhase

以下属性与事件的级差有关。

(1)bubbles

bubbles属性重返一个布尔值,表示近年来风浪是还是不是会冒泡。该属性为只读属性,只好在新建事件时退换。除非显式证明,伊芙nt布局函数生成的风浪,默许是不冒泡的。

function goInput(e) {
  if (!e.bubbles) {
    passItOn(e);
  } else {
    doOutput(e);
  }
}

上边代码依据事件是还是不是冒泡,调用差异的函数。

(2)event.eventPhase

eventPhase属性再次回到叁个整数值,表示事件目前所处的级差。

var phase = event.eventPhase;
  • 0,事件如今一向不生出。
  • 1,事件近来地处捕获阶段,即地处从祖先节点向指标节点的传遍进度中。该进程是从Window对象到Document节点,再到HTMLHtmlElement节点,直到目的节点的父节点截至。
  • 2,事件达到指标节点,即target属性指向的可怜节点。
  • 3,事件高居冒泡阶段,即地处从指标节点向祖先节点的反向传播进度中。该进程是从父节点一直到Window对象。独有bubbles属性为true时,这一个阶段才大概发生。
TiltFx.prototype._initEvents=function(){varself=this,moveOpts=self.options.movement;//mousemoveevent..this.tiltWrapper.addEventListener(mousemove,function(ev){requestAnimationFrame(function(){//mousepositionrelativetothedocument.varmousepos=getMousePos(ev),//documentscrolls.docScrolls={left:document.body.scrollLeft+document.documentElement.scrollLeft,top:document.body.scrollTop+document.documentElement.scrollTop},bounds=self.tiltWrapper.getBoundingClientRect(),//mousepositionrelativetothemainelement(tiltWrapper).relmousepos={x:mousepos.x-bounds.left-docScrolls.left,y:mousepos.y-bounds.top-docScrolls.top};//configurethemovementforeachimageelement.for(vari=0,len=self.imgElems.length;ilen;++i){varel=self.imgElems[i],rotX=moveOpts.rotateX?2*((i+1)*moveOpts.rotateX/self.options.extraImgs)/self.view.height*relmousepos.y-((i+1)*moveOpts.rotateX/self.options.extraImgs):0,rotY=moveOpts.rotateY?2*((i+1)*moveOpts.rotateY/self.options.extraImgs)/self.view.width*relmousepos.x-((i+1)*moveOpts.rotateY/self.options.extraImgs):0,rotZ=moveOpts.rotateZ?2*((i+1)*moveOpts.rotateZ/self.options.extraImgs)/self.view.width*relmousepos.x-((i+1)*moveOpts.rotateZ/self.options.extraImgs):0,transX=moveOpts.translateX?2*((i+1)*moveOpts.translateX/self.options.extraImgs)/self.view.width*relmousepos.x-((i+1)*moveOpts.translateX/self.options.extraImgs):0,transY=moveOpts.translateY?2*((i+1)*moveOpts.translateY/self.options.extraImgs)/self.view.height*relmousepos.y-((i+1)*moveOpts.translateY/self.options.extraImgs):0,transZ=moveOpts.translateZ?2*((i+1)*moveOpts.translateZ/self.options.extraImgs)/self.view.height*relmousepos.y-((i+1)*moveOpts.translateZ/self.options.extraImgs):0;el.style.WebkitTransform=perspective(+moveOpts.perspective+px)translate3d(+transX+px,+transY+px,+transZ+px)rotate3d(1,0,0,+rotX+deg)rotate3d(0,1,0,+rotY+deg)rotate3d(0,0,1,+rotZ+deg);el.style.transform=perspective(+moveOpts.perspective+px)translate3d(+transX+px,+transY+px,+transZ+px)rotate3d(1,0,0,+rotX+deg)rotate3d(0,1,0,+rotY+deg)rotate3d(0,0,1,+rotZ+deg);}});});//resetallwhenmouseleavesthemainwrapper.this.tiltWrapper.addEventListener(mouseleave,function(ev){setTimeout(function(){for(vari=0,len=self.imgElems.length;ilen;++i){varel=self.imgElems[i];el.style.WebkitTransform=perspective(+moveOpts.perspective+px)translate3d(0,0,0)rotate3d(1,1,1,0deg);el.style.transform=perspective(+moveOpts.perspective+px)translate3d(0,0,0)rotate3d(1,1,1,0deg);}},60);});//windowresizewindow.addEventListener(resize,throttle(function(ev){//recalculatetiltWrapperproperties:width/height/left/topself.view={width:self.tiltWrapper.offsetWidth,height:self.tiltWrapper.offsetHeight};},50));};

NodeList接口,HTMLCollection接口

节点目的都以单个节点,可是不经常会必要一种数据布局,能够容纳多少个节点。DOM提供三种接口,用于安顿这种节点的聚众:NodeList接口和HTMLCollection接口。

event.cancelable,event.defaultPrevented

以下属性与事件的私下认可行为有关。

(1)cancelable

cancelable属性再次来到八个布尔值,表示事件是不是能够打消。该属性为只读属性,只好在新建事件时改进。除非显式注解,Event构造函数生成的事件,暗中认可是不得以裁撤的。

var bool = event.cancelable;

借使要废除某些事件,须要在这里个事件方面调用preventDefault方法,那会阻止浏览器对某种事件安插的默许行为。

(2)defaultPrevented

defaultPrevented属性重回二个布尔值,表示该事件是或不是调用过preventDefault方法。

if (e.defaultPrevented) {
  // ...
}

咱俩得以观看,监听mousemove的事件管理函数中的总计相比较复杂,关键的有的就是在此边:

NodeList接口

多少属性和艺术再次来到的是一组节点,举个例子Node.childNodes、document.querySelectorAll(卡塔尔国。它们重临的都是三个布置了NodeList接口的对象。

NodeList接口有时回来二个动态群集,有的时候回来一个静态会集。所谓动态集合正是四个活的汇聚,DOM树删除或新扩张叁个一脉相连节点,都会登时反映在NodeList接口之中。Node.childNodes重返的,就是四个动态集合。

var parent = document.getElementById('parent');
parent.childNodes.length // 2
parent.appendChild(document.createElement('div'));
parent.childNodes.length // 3

上边代码中,parent.childNodes归来的是一个配置了NodeList接口的指标。当parent节点新扩充三个子节点现在,该目的的积极分子个数就大增了1。

document.querySelectorAll方法重回的是一个静态,DOM内部的变动,并不会实时反映在该措施的回来结果里面。

NodeList接口提供length属性和数字索引,由此得以像数组那样,使用数字索引抽取每种节点,可是它自个儿并非数组,无法接收pop或push之类数组特有的主意。

// 数组的继承链
myArray --> Array.prototype --> Object.prototype --> null

// NodeList的继承链
myNodeList --> NodeList.prototype --> Object.prototype --> null

从上面的世袭链能够看到,NodeList接口对象并不世袭Array.prototype,由此不富有数组接口提供的格局。假如要在NodeList接口使用数组方法,能够将NodeList接口对象转为真正的数组。

var div_list = document.querySelectorAll('div');
var div_array = Array.prototype.slice.call(div_list);

也得以通过上边包车型大巴主意调用。

var forEach = Array.prototype.forEach;

forEach.call(element.childNodes, function(child){
  child.parentNode.style.color = '#0F0';
});

地点代码让数组的forEach方法在NodeList接口目的上调用。

而是,遍历NodeList接口对象的首荐办法,依旧接收for循环。

for (var i = 0; i < myNodeList.length; ++i) {
  var item = myNodeList[i];
}

不用使用for…in循环去遍历NodeList接口对象,因为for…in循环会将非数字索引的length属性和底下要讲到的item方法,也遍历进去,并且不保障各种成员遍历的各类。

ES6新扩充的for…of循环,也可以正确遍历NodeList接口对象。

var list = document.querySelectorAll( 'input[type=checkbox]' );
for (var item of list) {
  item.checked = true;
}

NodeList接口提供item方法,接收贰个数字索引作为参数,重临该索引对应的成员。假如取不到成员,可能索引不合规,则赶回null。

nodeItem = nodeList.item(index)

// 实例
var divs = document.getElementsByTagName("div");
var secondDiv = divs.item(1);

地方代码中,由于数字索引从零发轫计数,所以抽取第一个分子,要运用数字索引1。

具有近似数组的目的,都得以利用方括号运算符收取成员,所以平日景况下,都以使用上面包车型大巴写法,而不行使item方法。

nodeItem = nodeList[index]

event.currentTarget,event.target

以下属性与事件的目的节点有关。

(1)currentTarget

currentTarget属性重回事件当前所在的节点,即正在进行的监听函数所绑定的十三分节点。作为相比较,target属性重临事件时有发生的节点。借使监听函数在捕获阶段和冒泡阶段触发,那么那多少个天性再次来到的值是不近似的。

function hide(e){
  console.log(this === e.currentTarget);  // true
  e.currentTarget.style.visibility = "hidden";
}

para.addEventListener('click', hide, false);

上面代码中,点击para节点,该节点会不可以预知。其余,在监听函数中,currentTarget属性实际上等同this对象。

(2)target

target属性重临触发事件的极其节点,即事件最早爆发的节点。纵然监听函数不在该节点触发,那么它与currentTarget属性重临的值是不等同的。

function hide(e){
  console.log(this === e.target);  // 有可能不是true
  e.target.style.visibility = "hidden";
}

// HTML代码为
// <p id="para">Hello <em>World</em></p>
para.addEventListener('click', hide, false);

地方代码中,即便在para节点的em子节点上边点击,则e.target指向em子节点,导致em子节点(即World部分)会不可以见到,且输出false。

在IE6—IE8之中,该属性的名字不是target,而是srcElement,由此常常能够看出上边这样的代码。

function hide(e) {
  var target = e.target || e.srcElement;
  target.style.visibility = 'hidden';
}
varel=self.imgElems[i],rotX=moveOpts.rotateX?2*((i+1)*moveOpts.rotateX/self.options.extraImgs)/self.view.height*relmousepos.y-((i+1)*moveOpts.rotateX/self.options.extraImgs):0,rotY=moveOpts.rotateY?2*((i+1)*moveOpts.rotateY/self.options.extraImgs)/self.view.width*relmousepos.x-((i+1)*moveOpts.rotateY/self.options.extraImgs):0,rotZ=moveOpts.rotateZ?2*((i+1)*moveOpts.rotateZ/self.options.extraImgs)/self.view.width*relmousepos.x-((i+1)*moveOpts.rotateZ/self.options.extraImgs):0,transX=moveOpts.translateX?2*((i+1)*moveOpts.translateX/self.options.extraImgs)/self.view.width*relmousepos.x-((i+1)*moveOpts.translateX/self.options.extraImgs):0,transY=moveOpts.translateY?2*((i+1)*moveOpts.translateY/self.options.extraImgs)/self.view.height*relmousepos.y-((i+1)*moveOpts.translateY/self.options.extraImgs):0,transZ=moveOpts.translateZ?2*((i+1)*moveOpts.translateZ/self.options.extraImgs)/self.view.height*relmousepos.y-((i+1)*moveOpts.translateZ/self.options.extraImgs):0;el.style.WebkitTransform=perspective(+moveOpts.perspective+px)translate3d(+transX+px,+transY+px,+transZ+px)rotate3d(1,0,0,+rotX+deg)rotate3d(0,1,0,+rotY+deg)rotate3d(0,0,1,+rotZ+deg);el.style.transform=perspective(+moveOpts.perspective+px)translate3d(+transX+px,+transY+px,+transZ+px)rotate3d(1,0,0,+rotX+deg)rotate3d(0,1,0,+rotY+deg)rotate3d(0,0,1,+rotZ+deg);

HTMLCollection接口

HTMLCollection接口与NodeList接口形似,也是节点的汇集,可是集结成员都以Element节点。该接口都以动态集结,节点的变化会实时反映在联谊中。document.links、docuement.forms、document.images等天性,重回的都以HTMLCollection接口对象。

配备了该接口的目的,具备length属性和数字索引,由此是贰个近乎于数组的对象。

item方法依照成员的岗位参数(从0开头),重临该成员。假使取不到成员或数字索引违法,则赶回null。

var c = document.images;
var img1 = c.item(10);

// 等价于下面的写法
var img1 = c[1];

namedItem方法遵照成员的ID属性或name属性,重返该成员。若无对应的分子,则赶回null。

// HTML代码为
// <form id="myForm"></form>
var elem = document.forms.namedItem("myForm");
// 等价于下面的写法
var elem = document.forms["myForm"];

是因为item方法和namedItem方法,都足以用方括号运算符替代,所以提出一律接收方括号运算符。

event.type,event.detail,event.timeStamp,event.isTrusted

以下属性与事件目的的其余新闻相关。

(1)type

type天性重临叁个字符串,表示事件类型,大小写敏感。

var string = event.type;

(2)detail

detail质量重返三个数值,表示事件的某种消息。具体意思与事件类型有关,对于鼠标事件,表示鼠标按钮在某些地点按下的次数,比方对于dblclick事件,detail属性的值总是2。

function giveDetails(e) {
  this.textContent = e.detail;
}

el.onclick = giveDetails;

(3)timeStamp

timeStamp品质再次来到三个皮秒时间戳,表示事件发生的时日。

var number = event.timeStamp;

Chrome在49版早前,这些天性再次回到的是三个大背头,单位是微秒(millisecond),表示从Unix纪元开端的年月戳。从49版开首,该属性重临的是一个高精度时间戳,也正是说,微秒之后还带四个人小数,准确到微秒。並且,这几个值不再从Unix纪元开头猜测,而是从PerformanceTiming.navigationStart早先总计,即意味着间隔顾客导航至该网页的年华。假如想将那几个值转为Unix纪元时间戳,将在计算event.timeStamp + performance.timing.navigationStart

上边是七个总括鼠标移动速度的事例,显示每秒移动的像素数量。

var previousX;
var previousY;
var previousT;

window.addEventListener('mousemove', function(event) {
  if (!(previousX === undefined ||
        previousY === undefined ||
        previousT === undefined)) {
    var deltaX = event.screenX - previousX;
    var deltaY = event.screenY - previousY;
    var deltaD = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));

    var deltaT = event.timeStamp - previousT;
    console.log(deltaD / deltaT * 1000);
  }

  previousX = event.screenX;
  previousY = event.screenY;
  previousT = event.timeStamp;
});

(4)isTrusted

isTrusted天性重返贰个布尔值,表示该事件是不是为真实客户触发。

var bool = event.isTrusted;

客商触发的风浪重返true,脚本触发的事件再次来到false

此地大家依照鼠标的职位,计算出了逐个图层对应的偏移量和旋转角度,然后对它们实行转移就能够。最终mouseleave其后,大家再把个个图层苏醒到起来地方就能够了。

ParentNode接口,ChildNode接口

不一致的节点除了三回九转Node接口以外,还只怕会三番五次其余接口。ParentNode接口用于获取当前节点的Element子节点,ChildNode接口用于拍卖当下节点的子节点(包括但不限于Element子节点)。

event.preventDefault()

preventDefault主意撤除浏览器对当前风浪的暗许行为,例如点击链接后,浏览器跳转到内定页面,只怕按一下空格键,页面向下滚动一段间隔。该方式生效的前提是,事件指标的cancelable属性为true,如果为false,则调用该形式未有其余效果。

该办法不会阻碍事件的进一层传播(stopPropagation措施可用于那么些指标)。只要在事件的无胫而行进程中(捕获阶段、指标阶段、冒泡阶段皆可),使用了preventDefault主意,该事件的私下认可方法就不会实行。

// HTML代码为
// <input type="checkbox" id="my-checkbox" />

var cb = document.getElementById('my-checkbox');

cb.addEventListener(
  'click',
  function (e){ e.preventDefault(); },
  false
);

上边代码为点击单选框的风浪,设置监听函数,废除私下认可行为。由于浏览器的暗中认可行为是选中单选框,所以这段代码会引致无计可施选中单选框。

应用那些法子,可感到文本输入框设置校验条件。若是用户的输入不符合条件,就不能将字符输入文本框。

function checkName(e) {
  if (e.charCode < 97 || e.charCode > 122) {
    e.preventDefault();
  }
}

地方函数设为文本框的keypress监听函数后,将一定要输入小写字母,不然输入事件的暗中同意事件(写入文本框)将被注销。

ParentNode接口

ParentNode接口用于获取Element子节点。Element节点、Document节点和DocumentFragment节点,安顿了ParentNode接口。凡是那三类节点,都持有以下八个属性,用于获取Element子节点。

(1)children

children属性再次来到二个动态的HTMLCollection集结,由方今节点的全体Element子节点组成。

下边代码遍历钦定节点的全体Element子节点。

if (el.children.length) {
  for (var i = 0; i < el.children.length; i++) {
    // ...
  }
}

(2)firstElementChild

firstElementChild属性重临当前节点的第八个Element子节点,假如不设有任何Element子节点,则赶回null。

document.firstElementChild.nodeName
// "HTML"

上边代码中,document节点的首先个Element子节点是<HTML>。

(3)lastElementChild

lastElementChild属性再次来到当前节点的结尾二个Element子节点,如若不设有任何Element子节点,则赶回null。

document.lastElementChild.nodeName
// "HTML"

上边代码中,document节点的末段二个Element子节点是<HTML>。

(4)childElementCount

childElementCount属性再次来到当前节点的全部Element子节点的多少。

event.stopPropagation()

stopPropagation措施阻碍事件在 DOM
中继续散播,幸免再触及定义在别的节点上的监听函数,可是不包涵在方今节点上新定义的事件监听函数。

function stopEvent(e) {
  e.stopPropagation();
}

el.addEventListener('click', stopEvent, false);

将上面函数内定为监听函数,会阻止事件更是冒泡到el节点的父节点。

ChildNode接口

ChildNode接口用于管理子节点(蕴含但不限于Element子节点)。Element节点、DocumentType节点和CharacterData接口,布置了ChildNode接口。凡是那三类节点(接口),都能够运用下边八个措施。可是现实的场馆是,除了第二个remove方法,近日尚无浏览器扶持后边八个方式。

(1)remove()

remove方法用于移除当前节点。

el.remove()

地点方法在DOM中移除了el节点。注意,调用这几个艺术的节点,是被移除的节点自身,并非它的父节点。

(2)before()

before方法用于在当下节点的近年来,插入叁个同级节点。假设参数是节点指标,插入DOM的正是该节点指标;如若参数是文件,插入DOM的正是参数对应的公文节点。

(3)after()

after方法用于在当下节点的末尾,插入四个同级节点。假诺参数是节点目的,插入DOM的正是该节点指标;假使参数是文件,插入DOM的正是参数对应的公文节点。

(4)replaceWith()

replaceWith方法运用参数钦命的节点,替换当前节点。要是参数是节点指标,替换当前节点的正是该节点目的;倘使参数是文件,替换当前节点的就是参数对应的公文节点。

event.stopImmediatePropagation()

stopImmediatePropagation办法阻碍同几个风云的别的监听函数被调用。

譬仿佛一个节点对于同叁个平地风波内定了多少个监听函数,那一个函数会基于增多的依次依次调用。只要个中有三个监听函数调用了stopImmediatePropagation方法,其余的监听函数就不会再推行了。

function l1(e){
  e.stopImmediatePropagation();
}

function l2(e){
  console.log('hello world');
}

el.addEventListener('click', l1, false);
el.addEventListener('click', l2, false);

上边代码在el节点上,为click事件增加了多少个监听函数l1和l2。由于l1调用了stopImmediatePropagation方法,所以l2不会被调用。

html元素

html要素是网页的根成分,document.documentElement就针对这么些成分。

(1)clientWidth属性,clientHeight属性

那五个本性再次回到视口(viewport)的尺寸,单位为像素。所谓“视口”,是指顾客最近可以知道的那某个网页的轻重

document.documentElement.clientWidthdocument.documentElement.clientHeight,基本上与window.innerWidthwindow.innerHeight形似。唯有二个有别于,前者不将滚动条总结在内(很鲜明,滚动条和工具栏会减小视口大小),而前面一个满含了滚动条的万丈和增长幅度。

(2)offsetWidth属性,offsetHeight属性

那三个属性重回html成分的宽窄和冲天,即网页的总宽度和总中度。

自定义事件和事件模拟

而外浏览器预订义的那多少个事件,顾客还是能够自定义事件,然后手动触发。

// 新建事件实例
var event = new Event('build');

// 添加监听函数
elem.addEventListener('build', function (e) { ... }, false);

// 触发事件
elem.dispatchEvent(event);

下面代码触发了自定义事件,该事件会层层提升冒泡。在冒泡进度中,假使有一个要素定义了该事件的监听函数,该监听函数就能够接触。

鉴于IE不帮助那几个API,假若在IE中自定义事件,须要动用后文的“老式方法”。

dataset属性

dataset属性用于操作HTML标签成分的data-*属性。上边是一个有data-*属性的div节点。

<div id="myDiv" data-id="myId"></div>

要读取data-id个性,可以从近年来节点的dataset.id质量读取。

var id = document.getElementById("myDiv").dataset.id;

要设置data-id属性,能够直接对dataset.id赋值。如若该属性不设有,将会被新建。

document.getElementById('myDiv').dataset.id = 'hello';

去除一个data-*品质,能够一向动用delete命令。

delete document.getElementById("myDiv").dataset.id;

除了dataset属性,也得以用getAttribute('data-foo')removeAttribute('data-foo')setAttribute('data-foo')hasAttribute('data-foo')等艺术操作data-*属性。

须要静心的是,dataset属性使用骆驼拼写法表示属性名,这代表data-hello-world会用dataset.helloWorld代表。而一旦那个时候留存三个data-helloWorld属性,该属性将不能够读取,也便是说,data-*属性自己只可以利用连词号,无法接受骆驼拼写法。

CustomEvent()

伊芙nt布局函数只好钦命事件名,无法在事变上绑定数据。借使需求在触及事件的同期,传入钦命的多寡,要求选取Custom伊芙nt布局函数生成自定义的事件目的。

var event = new CustomEvent('build', { 'detail': 'hello' });
function eventHandler(e) {
  console.log(e.detail);
}

上边代码中,Custom伊夫nt布局函数的率先个参数是事件名称,第2个参数是多少个对象,该对象的detail属性会绑定在事变指标之上。

上边是另一个例子。

var myEvent = new CustomEvent("myevent", {
  detail: {
    foo: "bar"
  },
  bubbles: true,
  cancelable: false
});

el.addEventListener('myevent', function(event) {
  console.log('Hello ' + event.detail.foo);
});

el.dispatchEvent(myEvent);

IE不帮忙这一个点子,能够用上面包车型大巴垫子函数模拟。

(function () {
  function CustomEvent ( event, params ) {
    params = params || { bubbles: false, cancelable: false, detail: undefined };
    var evt = document.createEvent( 'CustomEvent' );
    evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
    return evt;
   }

  CustomEvent.prototype = window.Event.prototype;

  window.CustomEvent = CustomEvent;
})();

tabindex属性

tabindex属性用来钦命,当前HTML成分节点是不是被tab键遍历,以致遍历的开始时期级。

var b1 = document.getElementById("button1");

b1.tabIndex = 1;

假定 tabindex = -1 ,tab键跳过当前因素。

比如 tabindex = 0
,表示tab键将遍历当前成分。假如八个因素未有安装tabindex,私下认可值正是0。

若果 tabindex 大于0,表示tab键优先遍历。值越大,就代表优先级越大。

事件的效仿

神蹟,供给在剧本中效仿触发某体系型的平地风波,此时就亟须接收这种事件的结构函数。

上面是三个经过Mouse伊夫nt布局函数,模拟触发click鼠标事件的事例。

function simulateClick() {
  var event = new MouseEvent('click', {
    'bubbles': true,
    'cancelable': true
  });
  var cb = document.getElementById('checkbox');
  cb.dispatchEvent(event);
}

页面地点相关属性

(1)offsetParent属性、offsetTop属性和offsetLeft属性

这两日性格提供Element对象在页面上的职责。

  • offsetParent:当前HTML成分的最左近的、况兼CSS的position属性不对等static的父成分。
  • offsetTop:当前HTML成分左上角相对于offsetParent的垂直位移。
  • offsetLeft:当前HTML成分左上角绝对于offsetParent的品位位移。

一旦Element对象的父对象都还没将position属性设置为非static的值(比方absolute或relative),则offsetParent属性指向body元素。其它,计算offsetTop和offsetLeft的时候,是从边框的左上角开端揣度,即Element对象的border宽度不计入offsetTop和offsetLeft。

自定义事件的老式写法

老式浏览器不自然帮助各系列型事件的布局函数。由此,有时为了合作,会用到有些非标准的方法。那几个办法今后会被逐步淘汰,不过当前浏览器还科学普及扶植。除非是为着同盟老式浏览器,尽量不要使用。

(1)document.createEvent()

document.createEvent方法用来新建钦命项目标风浪。它所生成的Event实例,能够流传dispatchEvent方法。

// 新建Event实例
var event = document.createEvent('Event');

// 事件的初始化
event.initEvent('build', true, true);

// 加上监听函数
document.addEventListener('build', doSomething, false);

// 触发事件
document.dispatchEvent(event);

createEvent方法选取几个字符串作为参数,大概的值参见下表“数据类型”一栏。使用了某一种“事件类型”,就必需使用相应的事件开端化方法。

事件类型 事件初始化方法
UIEvents event.initUIEvent
MouseEvents event.initMouseEvent
MutationEvents event.initMutationEvent
HTMLEvents event.initEvent
Event event.initEvent
CustomEvent event.initCustomEvent
KeyboardEvent event.initKeyEvent

(2)event.initEvent()

事件指标的init伊芙nt方法,用来初叶化事件目的,还能够向事件目的加多属性。该措施的参数必需是多个接收Document.createEvent()变迁的伊夫nt实例,并且必得在dispatch伊芙nt方法此前调用。

var event = document.createEvent('Event');
event.initEvent('my-custom-event', true, true, {foo:'bar'});
someElement.dispatchEvent(event);

initEvent方法能够承担四个参数。

  • type:事件名称,格式为字符串。
  • bubbles:事件是或不是相应冒泡,格式为布尔值。能够选取event.bubbles属性读取它的值。
  • cancelable:事件是不是能被吊销,格式为布尔值。可以接纳event.cancelable属性读取它的值。
  • option:为事件目的钦赐额外的特性。

style属性

style属性用来读写页面成分的行内CSS属性,详见本章《CSS操作》一节。

事件模拟的过时写法

事件模拟的非标准做法是,对document.create伊芙nt方法生成的风浪目的,使用相应的风浪最初化方法开展最早化。譬如,click事件指标归属MouseEvent对象,也归属UI伊芙nt对象,因而要用initMouseEvent方法或initUI伊夫nt方法开展起头化。

(1)event.initMouseEvent()

initMouse伊芙nt方法用来初步化Document.create伊芙nt方法新建的鼠标事件。该措施必得在事件新建(document.create伊芙nt方法)之后、触发(dispatch伊夫nt方法)此前调用。

initMouseEvent方法有非常短的参数。

event.initMouseEvent(type, canBubble, cancelable, view,
  detail, screenX, screenY, clientX, clientY,
  ctrlKey, altKey, shiftKey, metaKey,
  button, relatedTarget
);

澳门新葡萄京官网注册,地点那个参数的意思,参见MouseEvent布局函数的有的。

依傍并触发click事件的写法如下。

var simulateDivClick = document.createEvent('MouseEvents');

simulateDivClick.initMouseEvent('click',true,true,
  document.defaultView,0,0,0,0,0,false,
  false,false,0,null,null
);

divElement.dispatchEvent(simulateDivClick);

(2)UIEvent.initUIEvent()

UIEvent.initUIEvent()用来最初化一个UI事件。该方法必得在事件新建(document.create伊芙nt方法)之后、触发(dispatchEvent方法)早先调用。

event.initUIEvent(type, canBubble, cancelable, view, detail)

该办法的参数含义,能够敬重MouseEvent构造函数的一对。当中,detail参数是二个数值,含义与事件类型有关,对于鼠标事件,那几个值表示鼠标按钮在有些地点按下的次数。

var e = document.createEvent("UIEvent");
e.initUIEvent("click", true, true, window, 1);

Element对象的不二等秘书技

(1)选择子成分的方法

Element对象也配备了document对象的4个选项子成分的主意,并且用法完全等同。

  • querySelector方法
  • querySelectorAll方法
  • getElementsByTagName方法
  • getElementsByClassName方法

地点八个章程只用于选取Element对象的子节点。由此,能够动用链式写法来采撷子节点。

document.getElementById('header').getElementsByClassName('a')

各大浏览器对那多少个办法都支持美好,IE的气象如下:IE
6起头扶植getElementsByTagName,IE
8开首扶持querySelector和querySelectorAll,IE
9早先补助getElementsByClassName。

(2)elementFromPoint方法

该方法用于选拔在内定坐标的最上层的Element对象。

document.elementFromPoint(50,50)

上边代码了入选在(50,50卡塔尔那些坐标的最上层的丰富HTML成分。

(3)HTML成分的性质相关方法

  • hasAttribute(State of Qatar:重回贰个布尔值,表示Element对象是或不是有该属性。
  • getAttribute()
  • setAttribute()
  • removeAttribute()

(4)matchesSelector方法

该措施返回二个布尔值,表示Element对象是或不是切合某些CSS选拔器。

document.querySelector('li').matchesSelector('li:first-child')

以此办法要求加多浏览器前缀,须要写成mozMatchesSelector(卡塔尔国、webkitMatchesSelector(卡塔尔、oMatchesSelector(卡塔尔(قطر‎、msMatchesSelector(卡塔尔国。

(5)focus方法

focus方法用于将眼下页面包车型客车规范,转移到钦赐元素上。

document.getElementById('my-span').focus();

参照链接

  • Wilson Page, An Introduction To DOM
    Events
  • Mozilla Developer Network, Using Firefox 1.5
    caching
  • Craig Buckler, How to Capture CSS3 Animation Events in
    JavaScript
  • Ray Nicholus, You Don’t Need jQuery!:
    Events

table元素

报表有部分出色的DOM操作方法。

  • insertRow():在内定地点插入叁个新行(tr)。
  • deleteRow():在钦点地方删除一行(tr)。
  • insertCell():在内定地点插入一个单元格(td)。
  • deleteCell():在钦点位置删除二个单元格(td)。
  • createCaption():插入标题。
  • deleteCaption():删除标题。
  • createTHead():插入表头。
  • deleteTHead():删除表头。

下边是利用JavaScript生成表格的二个例证。

var table = document.createElement('table');
var tbody = document.createElement('tbody');
table.appendChild(tbody);

for (var i = 0; i <= 9; i++) {
  var rowcount = i + 1;
  tbody.insertRow(i);
  tbody.rows[i].insertCell(0);
  tbody.rows[i].insertCell(1);
  tbody.rows[i].insertCell(2);
  tbody.rows[i].cells[0].appendChild(document.createTextNode('Row ' + rowcount + ', Cell 1'));
  tbody.rows[i].cells[1].appendChild(document.createTextNode('Row ' + rowcount + ', Cell 2'));
  tbody.rows[i].cells[2].appendChild(document.createTextNode('Row ' + rowcount + ', Cell 3'));
}

table.createCaption();
table.caption.appendChild(document.createTextNode('A DOM-Generated Table'));

document.body.appendChild(table);

那几个代码卓殊易读,个中要求在意的正是insertRow和insertCell方法,选择二个表示地点的参数(从0最初的莫西干发型)。

table成分有以下属性:

  • caption:标题。
  • tHead:表头。
  • tFoot:表尾。
  • rows:行成分对象,该属性只读。
  • rows.cells:每一行的单元格对象,该属性只读。
  • tBodies:表体,该属性只读。

<h2 id=”5.2″>document节点</h2>

document节点概述

document节点是文档的根节点,每张网页都有友好的document节点。window.document属性就对准这么些节点。也正是说,只要浏览器初步载入HTML文书档案,那些节点指标就存在了,能够直接调用。

document节点有差异的措施能够收获。

  • 对此平日的网页,直接使用documentwindow.document
  • 对于iframe载入的网页,使用iframe节点的contentDocument属性。
  • 对Ajax操作重返的文档,使用XMLHttpRequest对象的responseXML属性。
  • 对此有个别节点包罗的文档,使用该节点的ownerDocument属性。

地点那各个document节点,都布署了Document接口,因而有一齐的本性和措施。当然,各自也会有一对投机特殊的属性和艺术,举例HTML和XML文档的document节点就分化。

document节点的属性

document节点有成都百货上千品质,用得超多的是上面那么些。

doctype,documentElement,defaultView,body,head,activeElement

以下属性指向文书档案内部的某部节点。

(1)doctype

对此HTML文书档案来说,document对象平时常有八个子节点。第叁个头节点是document.doctype,它是叁个指标,满含了当下文档类型(Document
Type Declaration,简写DTD)新闻。对于HTML5文书档案,该节点就代表<!DOCTYPE
html>。倘诺网页未有证明DTD,该属性再次回到null。

var doctype = document.doctype;

doctype // "<!DOCTYPE html>"
doctype.name // "html"

document.firstChild通常就赶回这些节点。

(2)documentElement

document.documentElement属性,表示近些日子文书档案的根节点(root)。它常常是document节点的第三个子节点,紧跟在document.doctype节点后边。

对于HTML网页,该属性再次来到HTML节点,代表<html lang=”en”>。

(3)defaultView

defaultView属性,在浏览器中回到document对象所在的window对象,不然重回null。

var win = document.defaultView;

(4)body

body属性重回当前文书档案的body或frameset节点,若是空头支票这里样的节点,就回去null。那天性格是可写的,假如对其写入二个新的节点,会促成原来的全体子节点被移除。

(4)head

head属性再次回到当前文书档案的head节点。假设当前文书档案有七个head,则赶回第贰个。

document.head === document.querySelector('head')

(5)activeElement

activeElement属性重临当前文书档案中拿走大旨的非常元素。客户日常能够使用tab键移动宗旨,使用空格键激活宗旨,比如假若难题在七个链接上,那个时候按一下空格键,就能跳转到该链接。

documentURI,URL,domain,lastModified,location,referrer,title,characterSet

以下属性重临文档音讯。

(1)documentURI,URL

documentURI属性和URL品质都回到当前文书档案的网站。分化之处是documentURI品质是有所文书档案都具有的,URL属性则是HTML文书档案唯有的。

document.documentURI === document.URL
// true

(2)domain

domain属性重回当前文书档案的域名。比如,某张网页的网站是
http://www.example.com/hello.html
domain属性就等于www.example.com。假诺不能够得到域名,该属性再次回到null

var badDomain = 'www.example.xxx';
if (document.domain === badDomain)
  window.close();

上边代码判定,借使当前域名等于内定域名,则关闭窗口。

二级域名的景况下,domain属性可以设置为对应的拔尖域名。譬喻,当前域名是sub.example.com,则domain属性能够设置为example.com。除却的写入,都以不得以的。

(3)lastModified

lastModified属性重临当前文书档案最终修改的流年戳,格式为字符串。

document.lastModified
// Tuesday, July 10, 2001 10:19:42

注意,lastModified性能的值是字符串,所以无法用来平素相比较,多个文书档案哪个人的日期更新,必要用Date.parse办法转成时间戳格式,本事拓宽比较。

if (Date.parse(doc1.lastModified) > Date.parse(doc2.lastModified)) {
  // ...
}

(4)location

document.location脾性重返一个只读的location指标,提供了近些日子文书档案的U昂科雷L音讯。

// 当前网址为 http://user:passwd@www.example.com:4097/path/a.html?x=111#part1
document.location.href // "http://user:passwd@www.example.com:4097/path/a.html?x=111#part1"
document.location.protocol // "http:"
document.location.host // "www.example.com:4097"
document.location.hostname // "www.example.com"
document.location.port // "4097"
document.location.pathname // "/path/a.html"
document.location.search // "?x=111"
document.location.hash // "#part1"
document.location.user // "user"
document.location.password // "passed"

// 跳转到另一个网址
document.location.assign('http://www.google.com')
// 优先从服务器重新加载
document.location.reload(true)
// 优先从本地缓存重新加载(默认值)
document.location.reload(false)
// 将location对象转为字符串,等价于document.location.href
document.location.toString()

虽然location品质重返的对象是只读的,可是足以将URL赋值给这一个个性,网页就能够自动跳转到内定网站。

document.location = 'http://www.example.com';
// 等同于
document.location.href = 'http://www.example.com';

在乎,接受地点的不二等秘书诀重新载入参数UAMG ONEL,跟客户点击链接跳转的效果与利益是雷同的。上三个网页依旧将保留在浏览器历史之中,点击“后退”开关就能够回去前一个网页。假使不指望顾客见到前多少个网页,能够选拔location.replace方法,浏览器history目的就能用新的网站,代替当前网址,那样的话,“后退”开关就不会回来当前网页了。

window.location.replace('http://www.example.com/otherpage.html');

location对象的search质量代表U奇骏L的查询字符串(包蕴?)。

// 查询字符串为 ?id=x&sort=name
var search = window.location.search;
search = search.slice(1); // 得到 'id=x&sort=name'
search = search.split('&'); // 得到数组 ['id=x', 'sort=name']

document.location属性与window.location品质等价。

document.location === window.location //true

正史上,IE曾经不一样意对document.location赋值,为了确认保障起见,提出事前使用window.location。要是只是仅仅地赢稳妥前网站,提出利用document.URL,语义性更加好。

(5)referrer

referrer属性重返二个字符串,表示近来文书档案的会见来源,假使是无计可施得到来源或是顾客直接键入网址,并非从别的网页点击,则赶回三个空字符串。

(6)title

title品质重临当前文书档案的标题,该属性是可写的。

document.title = '新标题';

(7)characterSet

characterSet属性重临渲染当前文档的字符集,比如UTF-8、ISO-8859-1。

readyState,designMode

以下属性与文档行为有关。

(1)readyState

readyState属性再次回到当前文书档案的处境,共有三种可能的值,加载HTML代码阶段(还没完结剖判)是“loading”,加载外界财富阶段是“interactive”,全体加载成功是“complete”。

上面包车型客车代码用来检查网页是还是不是加载成功。

// 基本检查
if (document.readyState === 'complete') {
  // ...
}

// 轮询检查
var interval = setInterval(function() {
  if (document.readyState === 'complete') {
    clearInterval(interval);
    // ...
  }
}, 100);

(2)designMode

designMode属性调节当前document是或不是可编写制定。常常会张开iframe的designMode属性,将其变为二个所见即所得的编辑器。

iframe_node.contentDocument.designMode = "on";

implementation,compatMode

以下属性重临文书档案的条件新闻。

(1)implementation

implementation属性重临二个目标,用来辨别当前条件计划了什么DOM相关接口。implementation属性的hasFeature方法,能够判定当前条件是还是不是安插了一定版本的特定接口。

document.implementation.hasFeature( 'HTML', '2.0')
// true

document.implementation.hasFeature('MutationEvents','2.0')
// true

地方代码表示,当前碰着计划了DOM HTML 2.0版和Mutation伊夫nts的2.0版。

(2)compatMode

compatMode属性重回浏览器管理文书档案的情势,恐怕的值为BackCompat(向后分外情势)和
CSS1Compat(严厉方式)。

anchors,embeds,forms,images,links,scripts,styleSheets

以下属性重返文书档案内部特定元素的集合(即HTMLCollection对象,详见下文)。那几个聚焦都是动态的,原节点有其余更换,马上会反映在集聚中。

(1)anchors

anchors属性重返网页中享有的a节点成分。注意,独有钦点了name属性的a成分,才会蕴藏在anchors属性之中。

(2)embeds

embeds属性再次回到网页中有着嵌入对象,即embed标签,再次来到的格式为附近数组的指标(nodeList)。

(3)forms

forms属性重回页面中具备表单。

var selectForm = document.forms[index];
var selectFormElement = document.forms[index].elements[index];

上边代码获取钦命表单的钦赐成分。

(4)images

images属性重临页面全数图片成分(即img标签)。

var ilist = document.images;

for(var i = 0; i < ilist.length; i++) {
  if(ilist[i].src == "banner.gif") {
    // ...
  }
}

上面代码在有着img标签中,寻找特定图片。

(4)links

links属性重临当前文书档案全体的链接成分(即a标签,可能说具备href属性的要素)。

(5)scripts

scripts属性重回当前文书档案的保有脚本(即script标签)。

var scripts = document.scripts;
if (scripts.length !== 0 ) {
  console.log("当前网页有脚本");
}

(6)styleSheets

styleSheets属性再次来到一个像样数组的对象,包罗了近来网页的持有样式表。该属性提供了样式表操作的接口。然后,每张样式表对象的cssRules属性,再次来到该样式表的有着CSS法则。那又方便了操作实际的CSS准则。

var allSheets = [].slice.call(document.styleSheets);

地点代码中,使用slice方法将document.styleSheets转为数组,以便于进一步处理。

document.cookie

document.cookie属性用来操作浏览器Cookie,详见《浏览器情状》一章的《Cookie》部分。

document对象的措施

document对象重要有以下一些格局。

open(),close(),write(),writeln()

document.open方法用于新建叁个文书档案,供write方法写入内容。它实质上等于解除当前文档,重新写入内容。不要将此措施与window.open(卡塔尔(قطر‎混淆,前面一个用来开发一个新窗口,与当下文书档案非亲非故。

document.close方法用于关闭open方法所新建的文书档案。一旦关闭,write方法就不可能写入内容了。如若再调用write方法,就相似又调用open方法,新建多个文书档案,再写入内容。

document.write方法用于向当前文书档案写入内容。只要当前文书档案还从未用close艺术关闭,它所写入的开始和结果就能够大增在本来就有内容的末尾。

// 页面显示“helloworld”
document.open();
document.write('hello');
document.write('world');
document.close();

借使页面已经渲染达成(DOMContentLoaded事件发生未来),再调用write方法,它会先调用open方法,擦除当前文书档案全体剧情,然后再写入。

document.addEventListener("DOMContentLoaded", function(event) {
  document.write('<p>Hello World!</p>');
});

// 等同于

document.addEventListener("DOMContentLoaded", function(event) {
  document.open();
  document.write('<p>Hello World!</p>');
  document.close();
});

若果在页面渲染进度中调用write情势,并不会调用open办法。(能够知晓成,open方法已调用,但close方法还没调用。)

<html>
<body>
hello
<script type="text/javascript">
  document.write("world")
</script>
</body>
</html>

在浏览器张开上边网页,将会来得“hello world”。

亟需在意的是,尽管调用close方法之后,不可能再用write方法写入内容,但此刻眼下页面的其余DOM节点依然会继续加载。

<html>
<head>
<title>write example</title>
<script type="text/javascript">
  document.open();
  document.write("hello");
  document.close();
</script>
</head>
<body>
world
</body>
</html>

在浏览器张开上边网页,将会显示“hello world”。

总体上看,除了某个特殊情状,应该尽量防止使用document.write其一法子。

document.writeln方法与write方式完全一致,除了会在输出内容的尾巴增多换行符。

document.write(1);
document.write(2);
// 12

document.writeln(1);
document.writeln(2);
// 1
// 2
//

注意,writeln措施加多的是ASCII码的换行符,渲染成HTML网页时不起功效。

hasFocus()

document.hasFocus方法重回二个布尔值,表示近来文书档案之中是还是不是有成分被激活或获得主题。

focused = document.hasFocus();

注意,有规范的文书档案必定被激活(active),反之不树立,激活的文书档案未必有关键。举例若是客户点击开关,从当下窗口跳出八个新窗口,该新窗口正是激活的,不过不负有宗旨。

querySelector(),getElementById(),querySelectorAll(),getElementsByTagName(),getElementsByClassName(),getElementsByName(),elementFromPoint()

以下情势用来选中当前文书档案中的成分。

(1)querySelector()

querySelector方式重临相配钦点的CSS选拔器的因初秋点。假诺有八个节点满意相配原则,则赶回第贰个万分的节点。若无开掘相配的节点,则赶回null

var el1 = document.querySelector('.myclass');
var el2 = document.querySelector('#myParent > [ng-click]');

querySelector格局无法选中CSS伪成分。

(2)getElementById()

getElementById主意重临相称钦命ID属性的因高商点。若无发觉相配的节点,则赶回null。

var elem = document.getElementById("para1");

注意,在探寻相配节点时,id本性是大大小小写敏感的。比如,要是某个节点的id属性是main,那么document.getElementById("Main")将返回null,并非钦定节点。

getElementById方法与querySelector主意都能得到成分节点,差异之处是querySelector情势的参数使用CSS选用器语法,getElementById主意的参数是HTML标签成分的id属性。

document.getElementById('myElement')
document.querySelector('#myElement')

地方代码中,五个措施都能入选id为myElement的因素,不过getElementById(卡塔尔国比querySelector(卡塔尔国成效高得多。

(3)querySelectorAll()

querySelectorAll情势再次回到相配内定的CSS采取器的具备节点,再次来到的是NodeList类型的对象。NodeList对象不是动态会集,所以成分节点的生成不能实时反映在回去结果中。

elementList = document.querySelectorAll(selectors);

querySelectorAll方法的参数,能够是逗号分隔的多个CSS采取器,再次来到全部相称个中贰个采用器的成分。

var matches = document.querySelectorAll('div.note, div.alert');

地方代码重回class属性是note或alert的div成分。

querySelectorAll方法援救复杂的CSS接收器。

// 选中data-foo-bar属性等于someval的元素
document.querySelectorAll('[data-foo-bar="someval"]');

// 选中myForm表单中所有不通过验证的元素
document.querySelectorAll('#myForm :invalid');

// 选中div元素,那些class含ignore的除外
document.querySelectorAll('DIV:not(.ignore)');

// 同时选中div,a,script三类元素
document.querySelectorAll('DIV, A, SCRIPT');

如果querySelectorAll方法和getElementsByTagName艺术的参数是字符串*,则会回去文书档案中的全数HTML元上秋点。

与querySelector方法一致,querySelectorAll方法不可能选中CSS伪成分。

(4)getElementsByClassName()

getElementsByClassName方法重回二个临近数组的对象(HTMLCollection类型的对象),包蕴了具有class名字适合钦点条件的要素(搜索范围蕴涵自家),成分的变型实时反映在回去结果中。这几个艺术不但能够在document对象上调用,也得以在其余因秋天点上调用。

// document对象上调用
var elements = document.getElementsByClassName(names);
// 非document对象上调用
var elements = rootElement.getElementsByClassName(names);

getElementsByClassName方法的参数,能够是四个空格分隔的class名字,重回同一时候兼有这个节点的成分。

document.getElementsByClassName('red test');

地方代码再次来到class同不常间负有red和test的成分。

(5)getElementsByTagName()

getElementsByTagName方法重临全数钦赐标签的成分(搜索范围包罗笔者)。重临值是一个HTMLCollection对象,也便是说,搜索结果是三个动态会集,任何因素的变通都会实时反映在回去的汇集中。那一个办法不但可以在document对象上调用,也能够在其余因孟秋点上调用。

var paras = document.getElementsByTagName("p");

地点代码重临当前文书档案的有所p成分节点。

当心,getElementsByTagName方法会将参数转为小写后,再进行搜索。

(6)getElementsByName()

getElementsByName方法用于采取具备name属性的HTML成分,举个例子form、img、frame、embed和object,重临贰个NodeList格式的靶子,不会实时反映要素的转移。

// 表单为 <form name="x"></form>
var forms = document.getElementsByName("x");
forms[0].tagName // "FORM"

瞩目,在IE浏览器选拔这些艺术,会将还未有name属性、但有同名id属性的成分也回到,所以name和id属性最棒设为不相通的值。

(7)elementFromPoint()

elementFromPoint方法再次回到坐落于页面钦命地方的要素。

var element = document.elementFromPoint(x, y);

地点代码中,elementFromPoint方法的参数x和y,分别是相对于前段时间窗口左上角的横坐标和纵坐标,单位是CSS像素。elementFromPoint方法重临坐落于那几个职位的DOM成分,要是该因素不可重临(比方文本框的滚动条),则赶回它的父成分(例如文本框)。借使坐标值无意义(比方负值),则赶回null。

createElement(),createTextNode(),createAttribute(),createDocumentFragment()

以下措施用于生成成分节点。

(1)createElement()

createElement方法用来生成HTML元高商点。

var element = document.createElement(tagName);
// 实例
var newDiv = document.createElement("div");

createElement方法的参数为要素的标签字,即成分节点的tagName属性。若是传入大写的标具名,会被转为小写。借使参数带有尖括号(即<和>)或许是null,会报错。

(2)createTextNode()

document.createTextNode办法用来扭转文书节点,参数为所要生成的文件节点的原委。

var newDiv = document.createElement('div');
var newContent = document.createTextNode('Hello');
newDiv.appendChild(newContent);

上边代码新建一个div节点和叁个文书节点,然后将文件节点插入div节点。

其一法子能够确认保障再次回到的节点,被浏览器当作txt文本渲染,实际不是当作HTML代码渲染。由此,能够用来体现客商的输入,幸免XSS攻击。

var div = document.createElement('div');
div.appendChild(document.createTextNode('Foo & bar'));
console.log(div.innerHTML)
// Foo & bar

上边代码中,createTextNode办法对超过号和小于号举办转义,进而保障即便顾客输入的内容涵盖恶意代码,也能科学展现。

急需小心的是,该方式不对单引号和双引号转义,所以不可能用来对HTML属性赋值。

function escapeHtml(str) {
  var div = document.createElement('div');
  div.appendChild(document.createTextNode(str));
  return div.innerHTML;
};

var userWebsite = '" onmouseover="alert('derp')" "';
var profileLink = '<a href="'%20+%20escapeHtml(userWebsite)%20+%20'">Bob</a>';
var div = document.getElemenetById('target');
div.innerHtml = profileLink;
// <a href="" onmouseover="alert('derp')" "">Bob</a>

上边代码中,由于createTextNode方法不转义双引号,招致onmouseover措施被注入了代码。

(3)createAttribute()

document.createAttribute方式生成贰个新的品质对象节点,并重返它。

attribute = document.createAttribute(name);

createAttribute方法的参数name,是性质的称号。

var node = document.getElementById("div1");
var a = document.createAttribute("my_attrib");
a.value = "newVal";
node.setAttributeNode(a);

// 等同于
var node = document.getElementById("div1");
node.setAttribute("my_attrib", "newVal");

(4)createDocumentFragment()

createDocumentFragment方法生成一个DocumentFragment对象。

var docFragment = document.createDocumentFragment();

DocumentFragment对象是叁个设有于内部存款和储蓄器的DOM片段,不过不归属当前文书档案,平常用来生成较复杂的DOM布局,然后插入当前文档。那样做的好处在于,因为DocumentFragment不归属当前文书档案,对它的其他更换,都不会抓住网页的双重渲染,比直接改良当前文书档案的DOM有越来越好的习性表现。

var docfrag = document.createDocumentFragment();

[1, 2, 3, 4].forEach(function(e) {
  var li = document.createElement("li");
  li.textContent = e;
  docfrag.appendChild(li);
});

document.body.appendChild(docfrag);

createEvent()

createEvent方法生成多个平地风波目的,该对象能够被element.dispatch伊芙nt方法应用,触发内定事件。

var event = document.createEvent(type);

create伊夫nt方法的参数是事件类型,比方UIEvents、Mouse伊芙nts、MutationEvents、HTML伊芙nts。

var event = document.createEvent('Event');
event.initEvent('build', true, true);
document.addEventListener('build', function (e) {
  // ...
}, false);
document.dispatchEvent(event);

createNodeIterator(),createTreeWalker()

以下格局用于遍历成分节点。

(1)createNodeIterator()

createNodeIterator方法再次来到多个DOM的子节点遍历器。

var nodeIterator = document.createNodeIterator(
  document.body,
  NodeFilter.SHOW_ELEMENT
);

地点代码再次来到body成分的遍历器。createNodeIterator方法的首先个参数为遍历器的根节点,第三个参数为所要遍历的节点类型,这里钦点为成分节点。别的品种还会有装有节点(NodeFilter.SHOW_ALL)、文本节点(NodeFilter.SHOW_TEXT)、商量节点(NodeFilter.SHOW_COMMENT)等。

所谓“遍历器”,在那边指可以用nextNode方法和previousNode方法依次遍历根节点的全部子节点。

var nodeIterator = document.createNodeIterator(document.body);
var pars = [];
var currentNode;

while (currentNode = nodeIterator.nextNode()) {
  pars.push(currentNode);
}

地点代码应用遍历器的nextNode方法,将根节点的全数子节点,依据从尾部到后面部分的次第,读入多少个数组。nextNode方法先回去遍历器的里边指针所在的节点,然后会将指针移向下一个节点。全体成员遍历完结后,再次回到null。previousNode方准则是先将指针移向上多少个节点,然后再次回到该节点。

var nodeIterator = document.createNodeIterator(
  document.body,
  NodeFilter.SHOW_ELEMENT
);

var currentNode = nodeIterator.nextNode();
var previousNode = nodeIterator.previousNode();

currentNode === previousNode // true

地点代码中,currentNode和previousNode都对准同二个的节点。

有叁个索要介怀之处,遍历器重返的第八个节点,总是根节点。

(2)createTreeWalker()

createTreeWalker方法再次来到二个DOM的子树遍历器。它与createNodeIterator方法的分别在于,前者只遍历子节点,而它遍历整个子树。

createTreeWalker方法的率先个参数,是所要遍历的根节点,第1个参数钦赐所要遍历的节点类型。

var treeWalker = document.createTreeWalker(
  document.body,
  NodeFilter.SHOW_ELEMENT
);

var nodeList = [];

while(treeWalker.nextNode()) nodeList.push(treeWalker.currentNode);

上边代码遍历body节点下属的具备因秋季点,将它们插入nodeList数组。

adoptNode(),importNode()

以下措施用于获取外界文书档案的节点。

(1)adoptNode()

adoptNode方法将有个别节点,从其原本所在的文书档案移除,插入当前文书档案,并回到插入后的新节点。

node = document.adoptNode(externalNode);

importNode方法从表面文书档案拷贝钦赐节点,插入当前文书档案。

var node = document.importNode(externalNode, deep);

(2)importNode()

importNode方法用于成立叁个外界节点的正片,然后插入当前文书档案。它的率先个参数是外表节点,第四个参数是一个布尔值,表示对外表节点是深拷贝依旧浅拷贝,默许是浅拷贝(false)。固然第一个参数是可选的,但是建议总是保留那一个参数,并设为true。

其余一个必要小心的地点是,importNode方法只是拷贝外界节点,那个时候该节点的父节点是null。下一步还必得将以此节点插入当前文书档案的DOM树。

var iframe = document.getElementsByTagName("iframe")[0];
var oldNode = iframe.contentWindow.document.getElementById("myNode");
var newNode = document.importNode(oldNode, true);
document.getElementById("container").appendChild(newNode);

上边代码从iframe窗口,拷贝一个内定节点myNode,插入当前文书档案。

addEventListener(),removeEventListener(),dispatchEvent()

以下多个格局与Document节点的平地风波有关。那么些主意都持续自EventTarget接口,详细介绍参见《伊芙nt对象》章节的《伊夫ntTarget》部分。

// 添加事件监听函数
document.addEventListener('click', listener, false);

// 移除事件监听函数
document.removeEventListener('click', listener, false);

// 触发事件
var event = new Event('click');
document.dispatchEvent(event);

<h2 id=”5.3″>Element对象</h2>

Element对象对应网页的HTML标签成分。每三个HTML标签元素,在DOM树上都会转形成叁个Element节点对象(以下简单称谓成分节点)。

要秋天点的nodeType属性都以1,然则不一样HTML标签生成的成分节点是不雷同的。JavaScript内部选拔分歧的布局函数,生成差别的Element节点,譬如<a>标签的节点目的由HTMLAnchorElement()构造函数生成,<button>标签的节点目的由HTMLButtonElement()构造函数生成。由此,成分节点不是一种对象,而是一组对象。

属性

attributes,id,tagName

以下属性重临成分节点的属性。

(1)attributes

attributes属性重临三个近乎数组的指标,成员是当前因素秋点的富有属性节点,各种数字索引对应二个属性节点(Attribute)对象。再次来到值中,全部成员都以动态的,即属性的变化会实时反映在结果集。

下边是三个HTML代码。

<p id="para">Hello World</p>

得到attributes成员的代码如下。

var para = document.getElementById('para');
var attr = para.attributes[0];

attr.name // id
attr.value // para

下边代码表达,通过attributes属性获取属性节点目标(attr)未来,能够透过name属性获取属性名(id),通过value属性获取属性值(para)。

潜心,属性节点的name属性和value属性,等同于nodeName属性和nodeValue属性。

上边代码是遍历一个要首秋点的保有属性。

var para = document.getElementsByTagName("p")[0];

if (para.hasAttributes()) {
  var attrs = para.attributes;
  var output = "";
  for(var i = attrs.length - 1; i >= 0; i--) {
    output += attrs[i].name + "->" + attrs[i].value;
  }
  result.value = output;
} else {
  result.value = "No attributes to show";
}

(2)id属性

id属性再次回到内定成分的id标志。该属性可读写。

(3)tagName属性

tagName属性再次来到钦点成分的大写的标具名,与nodeName属性的值杰出。

// 假定HTML代码如下
// Hello
var span = document.getElementById("span");
span.tagName // "SPAN"

innerHTML,outerHTML

以下属性重临成分节点的HTML内容。

(1)innerHTML

innerHTML属性重临该因素蕴含的HTML代码。该属性可读写,常用来安装有些节点的内容。

假定将该属性设为空,等于删除全数它含有的持有节点。

el.innerHTML = '';

地点代码等于将el节点形成了三个空节点,el原本富含的节点被整个删减。

小心,若是文本节点中蕴藏&、小于号(<)和超过号(%gt;),innerHTML属性会将它们转为实体形式&amp、&lt、&gt。

// HTML代码如下 <p id="para"> 5 > 3 </p>
document.getElementById('para').innerHTML
// 5 > 3

由于地点那么些缘故,诱致在innerHTML插入<script>标签,不会被实行。

var name = "<script>alert('haha')</script>";
el.innerHTML = name;

地方代码将脚本插入内容,脚本并不会实施。不过,innerHTML还是有平安风险的。

var name = "<img src=x onerror=alert(1)>";
el.innerHTML = name;

上边代码中,alert方法是会推行的。因而为了安全着想,借使插入的是文件,最佳用textContent属性代替innerHTML。

(2)outerHTML

outerHTML属性重返八个字符串,内容为钦点成分的保有HTML代码,富含它自己和含有的全体子成分。

// 假定HTML代码如下
// <div id="d"><p>Hello</p></div>

d = document.getElementById("d");
dump(d.outerHTML);

// '<div id="d"><p>Hello</p></div>'

outerHTML属性是可读写的,对它进行赋值,等于替换掉当前因素。

// 假定HTML代码如下
// <div id="container"><div id="d">Hello</div></div>

container = document.getElementById("container");
d = document.getElementById("d");
container.firstChild.nodeName // "DIV"
d.nodeName // "DIV"

d.outerHTML = "<p>Hello</p>";
container.firstChild.nodeName // "P"
d.nodeName // "DIV"

地方代码中,outerHTML属性重新赋值未来,内层的div成分就官样文章了,被p成分替换了。不过,变量d依然指向原本的div元素,那代表被轮换的DIV成分还存在于内部存款和储蓄器中。

设若钦定元素未有父节点,对它的outerTHML属性重新赋值,会抛出叁个漏洞百出。

document.documentElement.outerHTML = "test";  // DOMException

children,childElementCount,firstElementChild,lastElementChild

以下属性与成分节点的子元素相关。

(1)children

children属性重返三个形似数组的动态目的(实时反映变化),包涵方今成分节点的全数子成分。借使当前因素未有子成分,则赶回的对象富含零个分子。

// para是一个p元素节点
if (para.children.length) {
  var children = para.children;
    for (var i = 0; i < children.length; i++) {
      // ...
    }
}

(2)childElementCount

childElementCount属性再次来到当前因金天点包涵的子元素商点的个数。

(3)firstElementChild

firstElementChild属性再次回到第叁个子成分,若无,则赶回null。

(4)lastElementChild

lastElementChild属性重临最终一个子成分,若无,则赶回null。

nextElementSibling,previousElementSibling

以下属性与成分节点的同级成分相关。

(1)nextElementSibling

nextElementSibling属性重返钦命成分的后二个同级成分,若无则赶回null。

// 假定HTML代码如下
// <div id="div-01">Here is div-01</div>
// <div id="div-02">Here is div-02</div>
var el = document.getElementById('div-01');
el.nextElementSibling
// <div id="div-02">Here is div-02</div>

(2)previousElementSibling

previousElementSibling属性重回钦命成分的前八个同级成分,若无则赶回null。

className,classList

className属性用来读取和装置当前因素的class属性。它的值是二个字符串,每一个class之间用空格分割。

classList属性则赶回一个相符数组的对象,当前成分节点的每一种class便是其一目的的二个成员。

<div class="one two three" id="myDiv"></div>

位置那么些div成分的节点目的的className属性和classList属性,分别如下。

document.getElementById('myDiv').className
// "one two three"

document.getElementById('myDiv').classList
// {
//   0: "one"
//   1: "two"
//   2: "three"
//   length: 3
// }

从地点代码能够见到,className属性重返贰个空格分隔的字符串,而classList属性指向贰个好像数组的目的,该对象的length属性(只读)重返当前因素的class数量。

classList对象有下列方法。

  • add(卡塔尔(قطر‎:扩张贰个class。
  • remove(卡塔尔:移除多个class。
  • contains():检查当前成分是或不是带有有些class。
  • toggle(卡塔尔国:将有个别class移入或移出当前成分。
  • item(卡塔尔:再次回到内定索引地方的class。
  • toString(卡塔尔:将class的列表转为字符串。

myDiv.classList.add('myCssClass');
myDiv.classList.add('foo', 'bar');
myDiv.classList.remove('myCssClass');
myDiv.classList.toggle('myCssClass'); // 如果myCssClass不存在就加入,否则移除
myDiv.classList.contains('myCssClass'); // 返回 true 或者 false
myDiv.classList.item(0); // 返回第一个Class
myDiv.classList.toString();

下面对比一下,className和classList在丰硕和删除有些类时的写法。

// 添加class
document.getElementById('foo').className += 'bold';
document.getElementById('foo').classList.add('bold');

// 删除class
document.getElementById('foo').classList.remove('bold');
document.getElementById('foo').className =
document.getElementById('foo').className.replace(/^bold$/, '');

toggle方法能够担任一个布尔值,作为第二个参数。假设为true,则增添该属性;假若为false,则去除该属性。

el.classList.toggle('abc', boolValue);

// 等同于

if (boolValue){
  el.classList.add('abc');
} else {
  el.classList.remove('abc');
}

clientHeight,clientLeft,clientTop,clientWidth

以下属性与成分节点的可以预知区域的坐标相关。

(1)clientHeight

clientHeight属性再次来到成分节点的可以知道中度,包涵padding、但不富含水平滚动条、边框和margin的莫大,单位为像素。该属性能够总结获得,等于成分的CSS中度,加上CSS的padding中度,减去等级次序滚动条的可观(倘使存在水平滚动条)。

要是三个成分是足以滚动的,则clientHeight只总括它的可以知道部分的冲天。

(2)clientLeft

clientLeft属性等于成分节点左侧框(border)的大幅,单位为像素,包涵垂直滚动条的宽度,不包含左边的margin和padding。可是,除非制版方向是从右到左,且发生成分宽度溢出,不然是不容许存在侧面滚动条。要是该因素的展现设为display: inline,clientLeft一律为0,不管是不是留存侧面框。

(3)clientTop

clientTop属性等于网页成分最上端边框的宽度,不富含顶上部分的margin和padding。

(4)clientWidth

clientWidth属性等于网页成分的可以预知宽度,即蕴含padding、但不包含垂直滚动条(假诺部分话)、边框和margin的上涨的幅度,单位为像素。

万一三个因素是可以滚动的,则clientWidth只总括它的可以预知部分的幅度。

scrollHeight,scrollWidth,scrollLeft,scrollTop

以下属性与成分节点占领的总区域的坐标相关。

(1)scrollHeight

scrollHeight属性重返内定元素的总高度,包罗由于溢出而一点办法也未有浮现在网页的不可以知道部分。假诺二个成分是足以滚动的,则scrollHeight饱含整个因素的中度,不管是还是不是留存垂直滚动条。scrollHeight属性包含padding,但不包罗border和margin。该属性为只读属性。

一经不设有垂直滚动条,scrollHeight属性与clientHeight属性是相等的。假诺存在滚动条,scrollHeight属性总是大于clientHeight属性。当滚动条滚动到剧情尾部时,上面包车型大巴表明式为true。

element.scrollHeight - element.scrollTop === element.clientHeight

设若滚动条没有滚动到剧情尾巴部分,上边的表达式为false。这几个特点结合onscroll事件,能够剖断客户是不是滚动到了点名元素的平底,比方是不是滚动到了《使用须知》区块的底部。

var rules = document.getElementById("rules");
rules.onscroll = checking;

function checking(){
  if (this.scrollHeight - this.scrollTop === this.clientHeight) {
    console.log('谢谢阅读');
  } else {
    console.log('您还未读完');
  }
}

(2)scrollWidth

scrollWidth属性重回成分的总宽度,满含由于溢出容器而一点办法也想不出来体现在网页上的那某个大幅度,不管是或不是存在水平滚动条。该属性是只读属性。

(3)scrollLeft

scrollLeft属性设置或重回水平滚动条向侧边滚动的像素数量。它的值等于成分的最左侧与其可以见到的最侧面中间的离开。对于那么些从没滚动条或无需滚动的因素,该属性等于0。该属性是可读写属性,设置该属性的值,会以致浏览器将钦赐成分自动滚动到相应的岗位。

(4)scrollTop

scrollTop属性设置或重临垂直滚动条向下滚动的像素数量。它的值等于成分的顶上部分与其可知的参天职位之间的离开。对于那多少个从没滚动条或不须要滚动的成分,该属性等于0。该属性是可读写属性,设置该属性的值,会以致浏览器将内定成分自动滚动到相应地点。

document.querySelector('div').scrollTop = 150;

地点代码将div成分向下滚动150像素。

方法

hasAttribute(),getAttribute(),removeAttribute(),setAttribute()

以下方法与成分节点的品质相关。

(1)hasAttribute()

hasAttribute情势再次来到叁个布尔值,表示近年来因穷秋点是不是满含钦命的HTML属性。

var d = document.getElementById("div1");

if (d.hasAttribute("align")) {
  d.setAttribute("align", "center");
}

下面代码检查div节点是或不是带有align个性。如若有,则设置为“居中对齐”。

(2)getAttribute()

getAttribute艺术重临当前因九秋点的内定属性。假设钦命属性不设有,则赶回null

var div = document.getElementById('div1');
div.getAttribute('align') // "left"

(3)removeAttribute()

removeAttribute方法用于从当前因高商点移除属性。

// 原来的HTML代码
// <div id="div1" align="left" width="200px">
document.getElementById("div1").removeAttribute("align");
// 现在的HTML代码
// <div id="div1" width="200px">

(4)setAttribute()

setAttribute格局用于为眼下成分节点新扩充属性,或编辑已存在的习性。

var d = document.getElementById('d1');
d.setAttribute('align', 'center');

该方法会将具备属性名,都用作小写管理。对于这一个已存在的性质,该格局是编辑操作,不然就能新建属性。

上边是三个对img元素的src品质赋值的例证。

var myImage = document.querySelector('img');
myImage.setAttribute ('src', 'path/to/example.png');

绝大大多气象下,直接对品质赋值比使用该方法越来越好。

el.value = 'hello';
// or
el.setAttribute('value', 'hello');

querySelector(),querySelectorAll(),getElementsByClassName(),getElementsByTagName()

以下方式与收获当前成分节点的子成分相关。

(1)querySelector()

querySelector方法选择CSS选用器作为参数,再次来到父成分的首先个门道十分的子成分。

var content = document.getElementById('content');
var el = content.querySelector('p');

下边代码重回content节点的首先个p成分。

瞩目,借使CSS选用器有四个组成都部队分,比如div p,querySelector方法会把父元素思量在内。假定HTML代码如下。

<div id="outer">
  <p>Hello</p>
  <div id="inner">
    <p>World</p>
  </div>
</div>

那正是说,下边代码会选中首先个p成分。

var outer = document.getElementById('outer');
var el = outer.querySelector('div p');

(2)querySelectorAll()

querySelectorAll方法选拔CSS选拔器作为参数,再次回到一个NodeList对象,包蕴全部相配的子成分。

var el = document.querySelector('#test');
var matches = el.querySelectorAll('div.highlighted > p');

在CSS选用器有四个组成都部队分时,querySelectorAll方法也是会把父成分自己思索在内。

要么以下边包车型大巴HTML代码为例,上面代码会同一时间接选举中八个p元素。

var outer = document.getElementById('outer');
var el = outer.querySelectorAll('div p');

(3)getElementsByClassName()

getElementsByClassName方法再次回到贰个HTMLCollection对象,成员是当下因秋季点的有着相称钦定class的子成分。该办法与document.getElementsByClassName方法的用法形似,只是搜索范围不是整套文书档案,而是当前成分节点。

(4)getElementsByTagName()

getElementsByTagName方法重临叁个HTMLCollection对象,成员是现阶段成分节点的具有相配内定标签字的子成分。该措施与document.getElementsByClassName方法的用法相符,只是寻觅范围不是全体文档,而是当前因秋日点。其它,该办法搜索以前,会晤併将标具名转为小写。

closest(),matches()

(1)closest()

closest方法重临当前因首秋点的最相近的父元素(恐怕当前节点自己),条件是必得合营给定的CSS采取器。倘使不满意匹配,则赶回null。

纵然HTML代码如下。

<article>
  <div id="div-01">Here is div-01
    <div id="div-02">Here is div-02
      <div id="div-03">Here is div-03</div>
    </div>
  </div>
</article>

div-03节点的closet方法的例子如下。

var el = document.getElementById('div-03');
el.closest("#div-02") // div-02
el.closest("div div") // div-03
el.closest("article > div") //div-01
el.closest(":not(div)") // article

地点代码中,由于closet方法将最近因商节点也虚构在内,所以第2个closet方法重临div-03。

(2)match()

match方法再次回到叁个布尔值,表示近年来元素是或不是协作给定的CSS选取器。

if (el.matches(".someClass")) {
  console.log("Match!");
}

该措施满含浏览器前缀,上边包车型客车函数能够宽容差别的浏览器,而且在浏览器不协助时,自行安插这几个效率。

function matchesSelector(el, selector) {
  var p = Element.prototype;
  var f = p.matches
    || p.webkitMatchesSelector
    || p.mozMatchesSelector
    || p.msMatchesSelector
    || function(s) {
    return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
  };
  return f.call(el, selector);
}

// 用法
matchesSelector(
  document.getElementById('myDiv'),
  'div.someSelector[some-attribute=true]'
)

addEventListener(),removeEventListener(),dispatchEvent()

以下多个艺术与Element节点的平地风波有关。这个方法都一而再自EventTarget接口,详细介绍参见《Event对象》章节的《伊夫ntTarget》部分。

// 添加事件监听函数
el.addEventListener('click', listener, false);

// 移除事件监听函数
el.removeEventListener('click', listener, false);

// 触发事件
var event = new Event('click');
el.dispatchEvent(event);

getBoundingClientRect(),getClientRects()

以下措施重临成分节点的CSS盒状模型新闻。

(1)getBoundingClientRect()

getBoundingClientRect方法重返二个对象,该指标提供当前成分节点的轻重、它相对于视口(viewport)的职位等音信,基本上正是CSS盒状模型的从头到尾的经过。

var rect = obj.getBoundingClientRect();

上面代码中,getBoundingClientRect方法重返的对象,具备以下属性(全体为只读)。

  • bottom:成分后面部分相对于视口的纵坐标。
  • height:成分高度(等于bottom减去top)。
  • left:成分左上角相对于视口的坐标。
  • right:成分右侧界相对于视口的横坐标。
  • top:成分最上部相对于视口的纵坐标。
  • width:成分宽度(等于right减去left)。

鉴于成分相对于视口(viewport)的岗位,会趁机页面滚动变化,因而表示地方的四个属性值,都不是定位不变的。

小心,getBoundingClientRect方法的具备属性,都把边框(border属性)算作成分的一片段。也正是说,都以从边框外缘的各样点来测算。因而,width和height包蕴了成分本身

  • padding + border。

(1)getClientRects()

getClientRects方法重返多少个近乎数组的指标,里面是日前元素在页面上产生的有所矩形。各种矩形都有bottomheightleftrighttopwidth六本性子,表示它们绝对于视口的多少个坐标,以至自个儿的莫斯中国科学技术大学学和宽窄。

对此盒状成分(比方div和p),该措施再次回到的对象中唯有该因素贰个分子。对于行内成分(比方span、a、em),该方法重返的靶子有稍微个分子,决议于该因素在页面上据有多少行。

Hello World
Hello World
Hello World

上边代码是多少个行内成分span,假如它在页面上侵吞三行,getClientRects方法重回的目的就有三个成员,即使它在页面上吞没一行,getClientRects方法重临的对象就独有三个成员。

var el = document.getElementById('inline');
el.getClientRects().length // 3
el.getClientRects()[0].left // 8
el.getClientRects()[0].right // 113.908203125
el.getClientRects()[0].bottom // 31.200000762939453
el.getClientRects()[0].height // 23.200000762939453
el.getClientRects()[0].width // 105.908203125

以此艺术主要用以判定行内成分是不是换行,以至行内成分的每一行的职位偏移。

insertAdjacentHTML(),remove()

以下措施操作成分节点的DOM树。

(1)insertAdjacentHTML()

insertAdjacentHTML方法深入分析字符串,然后将转换的节点插入DOM树的钦定地方。

element.insertAdjacentHTML(position, text);

该措施接纳多少个参数,第二个是点名地点,第叁个是待深入分析的字符串。

钦定地方共有多少个。

  • beforebegin:在如今因金天点的眼下。
  • afterbegin:在当下成分节点的内部,插在它的第八个子成分早先。
  • beforeend:在现阶段成分节点的内部,插在它的末尾一个子成分之后。
  • afterend:在当前成分节点的前边。’

// 原来的HTML代码:<div id="one">one</div>
var d1 = document.getElementById('one');
d1.insertAdjacentHTML('afterend', '<div id="two">two</div>');
// 现在的HTML代码:
// <div id="one">one</div><div id="two">two</div>

该措施不是深透置换现成的DOM构造,那使得它的实践进程比innerHTML操作快得多。全数浏览器都协助这几个法子,蕴涵IE
6。

(2)remove()

remove方法用于将近期因秋季点从DOM树删除。

var el = document.getElementById('div-01');
el.remove();

scrollIntoView()

scrollIntoView方法滚动当前成分,步向浏览器的可以看到区域。

el.scrollIntoView(); // 等同于el.scrollIntoView(true)
el.scrollIntoView(false);

该办法能够担当二个布尔值作为参数。若是为true,表示成分的最上端与当前区域的可以知道部分的最上部对齐(前提是最近区域可滚动);若是为false,表示元素的底层与日前区域的可以看到部分的尾部对齐(前提是日前区域可滚动)。若无提供该参数,默感觉true。

<h2 id=”5.4″>Text节点和DocumentFragment节点</h2>

Text节点的定义

Text节点代表Element节点和Attribute节点的文本内容。要是七个节点只含有一段文本,那么它就有三个Text子节点,代表该节点的文件内容。常常我们应用Element节点的firstChild、nextSibling等品质获取Text节点,或许应用Document节点的createTextNode方法创建多个Text节点。

// 获取Text节点
var textNode = document.querySelector('p').firstChild;

// 创造Text节点
var textNode = document.createTextNode('Hi');
document.querySelector('div').appendChild(textNode);

浏览器原生提供贰个Text布局函数。它回到一个Text节点。它的参数正是该Text节点的文件内容。

var text1 = new Text();
var text2 = new Text("This is a text node");

只顾,由于空格也是七个字符,所以就算唯有二个空格,也会产生Text节点。

Text节点除了三番七遍Node节点的习性和格局,还接二连三了CharacterData接口。Node节点的脾性和方法请参见《Node节点》章节,这里不再另行介绍了,以下的品质和章程大多数来源于CharacterData接口。

Text节点的天性

data

data属性等同于nodeValue属性,用来安装或读取Text节点的开始和结果。

// 读取文本内容
document.querySelector('p').firstChild.data
// 等同于
document.querySelector('p').firstChild.nodeValue

// 设置文本内容
document.querySelector('p').firstChild.data = 'Hello World';

wholeText

wholeText属性将近日Text节点与毗邻的Text节点,作为多个安然无恙再次来到。大好些个气象下,wholeText属性的重临值,与data属性和textContent属性雷同。然而,有个别特殊情况会有异样。

比世尊讲来说,HTML代码如下。

<p id="para">A <em>B</em> C</p>

那时候,Text节点的wholeText属性和data属性,再次来到值相像。

var el = document.getElementById("para");
el.firstChild.wholeText // "A "
el.firstChild.data // "A "

唯独,一旦移除em节点,wholeText属性与data属性就能有反差,因为这个时候其实P节点上边富含了五个毗邻的Text节点。

el.removeChild(para.childNodes[1]);
el.firstChild.wholeText // "A C"
el.firstChild.data // "A "

length

length属性再次回到当前Text节点的文本长度。

(new Text('Hello')).length // 5

nextElementSibling

nextElementSibling属性重临紧跟在时下Text节点前边的特别同级Element节点。假设取不到如此的节点,则赶回null。

// HTML为
// <div>Hello <em>World</em></div>

var tn = document.querySelector('div').firstChild;
tn.nextElementSibling
// <em>World</em>

previousElementSibling

previousElementSibling属性重回当前Text节点前面近期的不胜Element节点。要是取不到那般的节点,则赶回null。

Text节点的主意

appendData(),deleteData(),insertData(),replaceData(),subStringData()

以下5个方法都以编辑Text节点文本内容的措施。

appendData方法用于在Text节点尾巴部分扩大字符串。

deleteData方法用于删除Text节点内部的子字符串,第1个参数为子字符串地点,首个参数为子字符串长度。

insertData方法用于在Text节点插入字符串,第二个参数为插入地点,第一个参数为插入的子字符串。

replaceData方法用于替换文本,第七个参数为轮番开头地方,第一个参数为需求被轮流掉的尺寸,第四个参数为新投入的字符串。

subStringData方法用于获取子字符串,第一个参数为子字符串在Text节点中的早先地方,第二个参数为子字符串长度。

// HTML代码为
// <p>Hello World</p>
var pElementText = document.querySelector('p').firstChild;

pElementText.appendData('!');
// 页面显示 Hello World!
pElementText.deleteData(7,5);
// 页面显示 Hello W
pElementText.insertData(7,'Hello ');
// 页面显示 Hello WHello
pElementText.replaceData(7,5,'World');
// 页面显示 Hello WWorld
pElementText.substringData(7,10);
// 页面显示不变,返回"World "

remove()

remove方法用于移除当前Text节点。

// HTML代码为
// <p>Hello World</p>

document.querySelector('p').firstChild.remove()
// 现在页面代码为
// <p></p>

splitText(),normalize()

splitText方法将Text节点相提并论,产生多个毗邻的Text节点。它的参数正是分开地点(从零开首),分割到该地方的字符前完工。假若分割地点荒诞不经,将报错。

分割后,该措施重回分割地点后方的字符串,而原Text节点产生只含有分割地方前方的字符串。

// html代码为 <p id="p">foobar</p>
var p = document.getElementById('p');
var textnode = p.firstChild;

var newText = textnode.splitText(3);
newText // "bar"
textnode // "foo"

normalize方法能够将毗邻的四个Text节点合併。

接上头的例子,splitText方法将三个Text节点分割成多个,normalize方法能够兑现逆操作,将它们统一。

p.childNodes.length // 2

// 将毗邻的两个Text节点合并
p.normalize();
p.childNodes.length // 1

DocumentFragment节点

DocumentFragment节点代表一个文书档案的片段,自个儿正是多少个整机的DOM树形布局。它从不父节点,不归属当前文书档案,操作DocumentFragment节点,要比直接操作DOM树快得多。

它平时用来塑造三个DOM构造,然后插入当前文书档案。document.createDocumentFragment方法,以至浏览器原生的DocumentFragment布局函数,能够成立叁个空的DocumentFragment节点。然后再利用此外DOM方法,向其增加子节点。

var docFrag = document.createDocumentFragment();
// or
var docFrag = new DocumentFragment();

var li = document.createElement("li");
li.textContent = "Hello World";
docFrag.appendChild(li);

document.queryselector('ul').appendChild(docFrag);

上面代码创制了多个DocumentFragment节点,然后将三个li节点增多在它里面,最后将DocumentFragment节点移动到最早的小说书档案。

假诺DocumentFragment节点被增加进最先的文章书档案,它自个儿就成为了空节点(textContent属性为空字符串)。如若想要保存DocumentFragment节点的剧情,能够利用cloneNode方法。

document
  .queryselector('ul')
  .appendChild(docFrag.cloneNode(true));

DocumentFragment节点对象未有团结的个性和方法,全体持续自Node节点和ParentNode接口。也正是说,DocumentFragment节点比Node节点多出以下多个个性。

  • children:重回四个动态的HTMLCollection集合对象,包蕴最近DocumentFragment对象的具有子成分节点。
  • firstElementChild:重临当前DocumentFragment对象的率先个子成分节点,若无则赶回null。
  • lastElementChild:重回当前DocumentFragment对象的最终一个子成分节点,若无则赶回null。
  • childElementCount:再次来到当前DocumentFragment对象的具有子成分数量。

别的,Node节点的享有办法,都领受DocumentFragment节点作为参数(比方Node.appendChild、Node.insertBefore)。这个时候,DocumentFragment的子节点(实际不是DocumentFragment节点自己)将插入当前节点。

<h2 id=”5.5″>Event对象</h2>

事件是一种异步编制程序的落到实处方式,本质上是前后相继各样组成都部队分之间的通讯。DOM帮助大气的风浪,本节介绍DOM的风浪编制程序。

EventTarget接口

DOM的风云操作(监听和接触),都定义在EventTarget接口。Element节点、document节点和window对象,都安排了那个接口。别的,XMLHttpRequest、奥迪oNode、奥迪(AudiState of QataroContext等浏览器内置对象,也计划了这些接口。

该接口正是八个主意,addEventListenerremoveEventListener用于绑定和移除监听函数,dispatchEvent用以触发事件。

addEventListener()

addEventListener办法用于在现阶段节点或对象上,定义贰个特定事件的监听函数。

target.addEventListener(type, listener[, useCapture]);

地方是应用格式,addEventListener方法选用多个参数。

  • type,事件名称,大小写不灵动。

  • listener,监听函数。钦定事件爆发时,会调用该监听函数。

  • useCapture,监听函数是还是不是在捕获阶段(capture)触发(参见后文《事件的散布》部分)。该参数是八个布尔值,默以为false(表示监听函数只在冒泡阶段被触发)。老式浏览器规定该参数必写,较新本子的浏览器允许该参数可选。为了保持宽容,建议总是写上该参数。

下边是叁个事例。

function hello(){
  console.log('Hello world');
}

var button = document.getElementById("btn");
button.addEventListener('click', hello, false);

地点代码中,add伊芙ntListener方法为button节点,绑定click事件的监听函数hello,该函数只在冒泡阶段触发。

能够应用add伊芙ntListener方法,为当前目的的同两个风云,增添三个监听函数。这个函数根据增加顺序触发,即先增多先触发。倘若为同多个事变屡次增添同二个监听函数,该函数只会实行一遍,多余的拉长将自动被删去(不必采纳removeEventListener方法手动去除)。

function hello(){
  console.log('Hello world');
}

document.addEventListener('click', hello, false);
document.addEventListener('click', hello, false);

实施上边代码,点击文书档案只会输出一行“Hello world”。

假若愿意向监听函数字传送递参数,能够用佚名函数包装一下监听函数。

function print(x) {
  console.log(x);
}

var el = document.getElementById("div1");
el.addEventListener("click", function(){print('Hello')}, false);

地方代码通过无名氏函数,向监听函数print传递了四个参数。

removeEventListener()

removeEventListener方法用来移除addEventListener方法加多的事件监听函数。

div.addEventListener('click', listener, false);
div.removeEventListener('click', listener, false);

remove伊夫ntListener方法的参数,与add伊夫ntListener方法完全一致。它对第叁个参数“事件类型”,也是大大小小写不灵敏。

只顾,removeEventListener方法移除的监听函数,必得与相应的add伊芙ntListener方法的参数别无二致,并且在同一个要季秋点,不然无效。

dispatchEvent()

dispatchEvent方式在时下节点上接触钦点事件,进而触发监听函数的实践。该格局再次回到三个布尔值,只要有贰个监听函数调用了Event.preventDefault(),则再次回到值为false,否则为true

target.dispatchEvent(event)

dispatchEvent情势的参数是一个Event指标的实例。

para.addEventListener('click', hello, false);
var event = new Event('click');
para.dispatchEvent(event);

地点代码在近些日子节点触发了click事件。

如果dispatchEvent方法的参数为空,只怕不是二个一蹴而就的风浪指标,将报错。

下边代码依据dispatchEvent方法的重临值,判定事件是或不是被撤废了。

var canceled = !cb.dispatchEvent(event);
  if (canceled) {
    console.log('事件取消');
  } else {
    console.log('事件未取消');
  }
}

监听函数

监听函数(listener)是事件时有爆发时,程序所要推行的函数。它是事件驱动编制程序形式的机要编程情势。

DOM提供三种艺术,能够用来为事件绑定监听函数。

HTML标签的on-属性

HTML语言允许在要素标签的质量中,间接定义有些事件的监听代码。

<body onload="doSomething()">
<div onclick="console.log('触发事件')">

位置代码为body节点的load事件、div节点的click事件,钦点了监听函数。

行使这么些措施钦点的监听函数,只会在冒泡阶段触发。

注意,使用这种方法时,on-性子的值是将会进行的代码,并非“监听函数”。

<!-- 正确 -->
<body onload="doSomething()">

<!-- 错误 -->
<body onload="doSomething">

一旦钦赐的风浪发生,on-性情的值是样子传入JavaScript引擎试行。由此一旦要推行函数,不要遗忘加上一对圆括号。

另外,Element节点的setAttribute主意,其实设置的也是这种意义。

el.setAttribute('onclick', 'doSomething()');

Element节点的平地风波性质

Element节点有事件性质,可以定义监听函数。

window.onload = doSomething;

div.onclick = function(event){
  console.log('触发事件');
};

动用这一个艺术内定的监听函数,只会在冒泡阶段触发。

addEventListener方法

通过Element节点、document节点、window对象的addEventListener办法,也得以定义事件的监听函数。

window.addEventListener('load', doSomething, false);

addEventListener方法的详细介绍,参见本节EventTarget接口的一部分。

在地方二种方式中,第一种“HTML标签的on-属性”,违反了HTML与JavaScript代码相分离的准绳;第二种“Element节点的风浪性质”的劣点是,同多少个风云只好定义三个监听函数,也就是说,倘诺定义一次onclick属性,后叁回定义会覆盖前二回。因而,那二种方法都不引入应用,除非是为了程序的包容难点,因为具有浏览器都帮助那三种艺术。

addEventListener是引入的钦赐监听函数的艺术。它有如下优点:

  • 能够本着同二个事件,增加多少个监听函数。

  • 能够内定在哪个阶段(捕获阶段可能冒泡阶段)触发回监听函数。

  • 除了DOM节点,还足以布署在window、XMLHttpRequest等目的方面,等于统一了百分百JavaScript的监听函数接口。

this对象的指向

实则编制程序中,监听函数内部的this对象,平时供给针对触发事件的那些Element节点。

add伊夫ntListener方法钦定的监听函数,内部的this对象总是指向触发事件的不得了节点。

// HTML代码为
// <p id="para">Hello</p>

var id = 'doc';
var para = document.getElementById('para');

function hello(){
  console.log(this.id);
}

para.addEventListener('click', hello, false);

实施下面代码,点击p节点会输出para。那是因为监听函数被“拷贝”成了节点的一天性质,使用下边包车型地铁写法,会看得更明了。

para.onclick = hello;

若是将监听函数铺排在Element节点的on-属性上边,this不会指向触发事件的要素商点。

<p id="para" onclick="hello()">Hello</p>
<!-- 或者使用JavaScript代码  -->
<script>
  pElement.setAttribute('onclick', 'hello()');
</script>

推行上边代码,点击p节点会输出doc。那是因为此地只是调用hello函数,而hello函数实际是在大局功能域实践,相当于下边包车型客车代码。

para.onclick = function(){
  hello();
}

一种缓慢解决方法是,不引进函数成效域,间接在on-属性写入所要施行的代码。因为on-属性是在时下节点上施行的。

<p id="para" onclick="console.log(id)">Hello</p>
<!-- 或者 -->
<p id="para" onclick="console.log(this.id)">Hello</p>

地点两行,最终输出的都以para。

小结一下,以下写法的this对象都指向Element节点。

// JavaScript代码
element.onclick = print
element.addEventListener('click', print, false)
element.onclick = function () {console.log(this.id);}

// HTML代码
<element onclick="console.log(this.id)">

以下写法的this对象,都照准全局对象。

// JavaScript代码
element.onclick = function (){ doSomething() };
element.setAttribute('onclick', 'doSomething()');

// HTML代码
<element onclick="doSomething()">

事件的传入

盛传的多个阶段

当多少个风浪时有发生现在,它会在差异的DOM节点之间传播(propagation)。这种传播分成四个级次:

  • 第一品级:从window对象传导到目的节点,称为“捕获阶段”(capture
    phase)。

  • 第二等级:在对象节点上接触,称为“目的阶段”(target phase)。

  • 其三阶段:从目的节点传导回window对象,称为“冒泡阶段”(bubbling
    phase)。

这种三品级的不翼而飞模型,会使得贰个事件在多少个节点上接触。比方,如若div节点之中嵌套八个p节点。

<div>
  <p>Click Me</p>
</div>

假设对那五个节点的click事件都设定监听函数,则click事件会被触发伍回。

var phases = {
  1: 'capture',
  2: 'target',
  3: 'bubble'
};

var div = document.querySelector('div');
var p = document.querySelector('p');

div.addEventListener('click', callback, true);
p.addEventListener('click', callback, true);
div.addEventListener('click', callback, false);
p.addEventListener('click', callback, false);

function callback(event) {
  var tag = event.currentTarget.tagName;
  var phase = phases[event.eventPhase];
  console.log("Tag: '" + tag + "'. EventPhase: '" + phase + "'");
}

// 点击以后的结果
// Tag: 'DIV'. EventPhase: 'capture'
// Tag: 'P'. EventPhase: 'target'
// Tag: 'P'. EventPhase: 'target'
// Tag: 'DIV'. EventPhase: 'bubble'

地点代码表示,click事件被触发了肆回:p节点的抓获阶段和冒泡阶段各1次,div节点的捕获阶段和冒泡阶段各1次。

  1. 抓获阶段:事件从div向p传播时,触发div的click事件;
  2. 对象阶段:事件从div达到p时,触发p的click事件;
  3. 目的阶段:事件离开p时,触发p的click事件;
  4. 冒泡阶段:事件从p传回div时,再度触发div的click事件。

注意,顾客点击网页的时候,浏览器总是假定click事件的靶子节点,就是点击地点的嵌套最深的百般节点(嵌套在div节点的p节点)。

事件传播的最上层对象是window,接着依次是document,html(document.documentElement)和body(document.dody)。也便是说,尽管body成分中有一个div成分,点击该因素。事件的散播顺序,在捕获阶段依次为window、document、html、body、div,在冒泡阶段依次为div、body、html、document、window。

事件的代办

是因为事件会在冒泡阶段发展传播到父节点,因而能够把手节点的监听函数定义在父节点上,由父节点的监听函数统一管理四个子成分的轩然大波。这种措施叫做事件的代理(delegation)。

var ul = document.querySelector('ul');

ul.addEventListener('click', function(event) {
  if (event.target.tagName.toLowerCase() === 'li') {
    // some code
  }
});

上边代码的click事件的监听函数定义在ul节点,不过实际,它管理的是子节点li的click事件。那样做的功利是,只要定义一个监听函数,就会处理几个子节点的事件,并且以后再增添子节点,监听函数仍然有效。

只要期待事件到有些节点停止,不再传播,能够动用事件指标的stopPropagation方法。

p.addEventListener('click', function(event) {
  event.stopPropagation();
});

应用方面包车型大巴代码现在,click事件在冒泡阶段到达p节点今后,就不再发展(父节点的趋向)传播了。

然则,stopPropagation方法不会堵住p节点上的别样click事件的监听函数。假如想要不再触发那个监听函数,能够应用stopImmediatePropagation方法。

p.addEventListener('click', function(event) {
 event.stopImmediatePropagation();
});

p.addEventListener('click', function(event) {
 // 不会被触发
});

Event对象

事件发生之后,会转移贰个风云目的,作为参数字传送给监听函数。浏览器原生提供三个Event对象,全体的平地风波都是那么些目的的实例,恐怕说继承了Event.prototype对象。

伊芙nt对象自己正是二个构造函数,能够用来生成新的实例。

event = new Event(typeArg, eventInit);

Event构造函数选取三个参数。第贰个参数是字符串,表示事件的称呼;第二个参数是多少个对象,表示事件目的的布署。该参数能够有以下两本天性。

  • bubbles:布尔值,可选,默以为false,表示事件指标是否冒泡。

  • cancelable:布尔值,可选,默以为false,表示事件是不是能够被撤回。

var ev = new Event("look", {"bubbles":true, "cancelable":false});
document.dispatchEvent(ev);

下边代码新建二个look事件实例,然后选取dispatchEvent方法触发该事件。

IE8及以下版本,事件指标不作为参数字传送递,而是经过window对象的event属性读取,并且事件目的的target属性叫做srcElement属性。所以,早前取得事件信息,往往要写成上面那样。

function myEventHandler(event) {
  var actualEvent = event || window.event;
  var actualTarget = actualEvent.target || actualEvent.srcElement;
  // ...
}

地点的代码只是为了求证早前的次序为啥那样写,在新代码中,那样的写法不应该再用了。

以下介绍伊夫nt实例的性质和艺术。

bubbles,eventPhase

以下属性与事件的级差有关。

(1)bubbles

bubbles属性再次来到一个布尔值,表示近期风浪是还是不是会冒泡。该属性为只读属性,只好在新建事件时退换。除非显式注明,伊芙nt结构函数生成的风浪,暗许是不冒泡的。

function goInput(e) {
  if (!e.bubbles) {
    passItOn(e);
  } else {
    doOutput(e);
  }
}

地点代码依照事件是还是不是冒泡,调用差异的函数。

(2)eventPhase

eventPhase属性重临二个子弹头值,表示事件前段时间所处的节点。

var phase = event.eventPhase;
  • 0,事件近期没有发生。
  • 1,事件近期高居捕获阶段,即地处从祖先节点向指标节点的传遍过程中。该进度是从Window对象到Document节点,再到HTMLHtmlElement节点,直到目的节点的父节点甘休。
  • 2,事件到达目标节点,即target属性指向的不胜节点。
  • 3,事件高居冒泡阶段,即地处从目的节点向祖先节点的反向传播进程中。该进度是从父节点一向到Window对象。独有bubbles属性为true时,那个等第才大概发生。

cancelable,defaultPrevented

以下属性与事件的暗许行为有关。

(1)cancelable

cancelable属性再次回到二个布尔值,表示事件是或不是能够收回。该属性为只读属性,只好在新建事件时改换。除非显式表明,伊夫nt布局函数生成的风云,私下认可是不得以收回的。

var bool = event.cancelable;

假如要吊销某些事件,供给在这么些事件方面调用preventDefault方法,那会阻碍浏览器对某种事件陈设的暗许行为。

(2)defaultPrevented

defaultPrevented属性再次来到多个布尔值,表示该事件是不是调用过preventDefault方法。

if (e.defaultPrevented) {
  // ...
}

currentTarget,target

以下属性与事件的对象节点有关。

(1)currentTarget

currentTarget属性重返事件当前所在的节点,即正在实施的监听函数所绑定的不得了节点。作为相比,target属性再次来到事件发生的节点。如若监听函数在破获阶段和冒泡阶段触发,那么这两脾个性再次回到的值是不均等的。

function hide(e){
  console.log(this === e.currentTarget);  // true
  e.currentTarget.style.visibility = "hidden";
}

para.addEventListener('click', hide, false);

上边代码中,点击para节点,该节点会不可以见到。此外,在监听函数中,currentTarget属性实际上等同this对象。

(2)target

target属性再次回到触发事件的可怜节点,即事件最早发生的节点。固然监听函数不在该节点触发,那么它与currentTarget属性再次来到的值是分歧的。

function hide(e){
  console.log(this === e.target);  // 有可能不是true
  e.target.style.visibility = "hidden";
}

// HTML代码为
// <p id="para">Hello <em>World</em></p>
para.addEventListener('click', hide, false);

地点代码中,若是在para节点的em子节点上边点击,则e.target指向em子节点,导致em子节点(即World部分)会不可知,且输出false。

在IE6—IE8之中,该属性的名字不是target,而是srcElement,由此日常能够看看上边那样的代码。

function hide(e) {
  var target = e.target || e.srcElement;
  target.style.visibility = 'hidden';
}

type,detail,timeStamp,isTrusted

以下属性与事件指标的其余音讯相关。

(1)type

type属性再次回到八个字符串,表示事件类型,具体的值同add伊芙ntListener方法和removeEventListener方法的率先个参数一致,大小写不灵动。

var string = event.type;

(2)detail

detail属性再次来到七个数值,表示事件的某种消息。具体意思与事件类型有关,对于鼠标事件,表示鼠标开关在有些地方按下的次数,比如对于dblclick事件,detail属性的值总是2。

function giveDetails(e) {
  this.textContent = e.detail;
}

el.onclick = giveDetails;

(3)timeStamp

timeStamp属性重回一个飞秒时间戳,表示事件时有爆发的时日。

var number = event.timeStamp;

Chrome在49版此前,那些性情重临的是一个平头,单位是纳秒(millisecond),表示从Unix纪元初叶的年月戳。从49版先河,该属性重临的是三个高精度时间戳,也正是说,飞秒之后还带肆个人小数,准确到飞秒。并且,这么些值不再从Unix纪元开首思谋,而是从PerformanceTiming.navigationStart初阶总括,即意味着间距客户导航至该网页的大运。纵然想将那么些值转为Unix纪元时间戳,将要计算event.timeStamp + performance.timing.navigationStart

下边是叁个思索鼠标移动速度的例证,呈现每秒移动的像素数量。

var previousX;
var previousY;
var previousT;

window.addEventListener('mousemove', function(event) {
  if (!(previousX === undefined ||
        previousY === undefined ||
        previousT === undefined)) {
    var deltaX = event.screenX - previousX;
    var deltaY = event.screenY - previousY;
    var deltaD = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));

    var deltaT = event.timeStamp - previousT;
    console.log(deltaD / deltaT * 1000);
  }

  previousX = event.screenX;
  previousY = event.screenY;
  previousT = event.timeStamp;
});

(4)isTrusted

isTrusted属性再次回到一个布尔值,表示该事件是不是能够相信。

var bool = event.isTrusted;

Firefox浏览器中,客户触发的平地风波会回来true,脚本触发的平地风波重临false;IE浏览器中,除了使用create伊芙nt方法生成的风云,全数别的事件都回去true;Chrome浏览器不支持该属性。

preventDefault()

preventDefault方法撤消浏览器对当前风浪的默许行为,比方点击链接后,浏览器跳转到内定页面,也许按一下空格键,页面向下滚动一段间距。该办法生效的前提是,事件的cancelable属性为true,假如为false,则调用该措施未有别的效用。

该方法不会阻拦事件的越发扩散(stopPropagation方法可用来那个目标)。只要在事件的传播进程中(捕获阶段、指标阶段、冒泡阶段皆可),使用了preventDefault方法,该事件的私下认可方法就不会实施。

// HTML代码为
// <input type="checkbox" id="my-checkbox" />

var cb = document.getElementById('my-checkbox');

cb.addEventListener(
  'click',
  function (e){ e.preventDefault(); },
  false
);

地点代码为点击单选框的事件,设置监听函数,撤消默许行为。由于浏览器的暗中同意行为是选中单选框,所以这段代码会产生束手无策选中单选框。

选取那个主意,可认为文本输入框设置校验条件。即使客商的输入不相符条件,就不能将字符输入文本框。

function checkName(e) {
  if (e.charCode < 97 || e.charCode > 122) {
    e.preventDefault();
  }
}

地方函数设为文本框的keypress监听函数后,将只好输入小写字母,不然输入事件的私下认可事件(写入文本框)将被吊销。

万一监听函数最终回到布尔值false(即return
false),浏览器也不会触发暗中同意行为,与preventDefault方法有等同效果。

stopPropagation()

stopPropagation方法阻碍事件在DOM中一连散播,防止再接触定义在别的节点上的监听函数,可是不包括在现阶段节点上新定义的事件监听函数。

function stopEvent(e) {
  e.stopPropagation();
}

el.addEventListener('click', stopEvent, false);

将方面函数钦点为监听函数,会阻拦事件更加的冒泡到el节点的父节点。

stopImmediatePropagation()

stopImmediatePropagation方法阻碍同一个平地风波的此外监听函数被调用。

只要同三个节点对于同三个事变钦定了多少个监听函数,这么些函数会依赖增多的种种依次调用。只要个中有一个监听函数调用了stopImmediatePropagation方法,别的的监听函数就不会再进行了。

function l1(e){
  e.stopImmediatePropagation();
}

function l2(e){
  console.log('hello world');
}

el.addEventListener('click', l1, false);
el.addEventListener('click', l2, false);

下面代码在el节点上,为click事件增添了五个监听函数l1和l2。由于l1调用了stopImmediatePropagation方法,所以l2不会被调用。

鼠标事件

事件体系

鼠标事件指与鼠标相关的平地风波,首要有以下部分。

(1)click事件

click事件当顾客在Element节点、document节点、window对象上,单击鼠标(恐怕按下回车键)时接触。

“鼠标单击”定义为,顾客在同一个岗位达成叁次mousedown动作和mouseup动作。它们的触发顺序是:mousedown第一触及,mouseup进而触发,click最后触发。

下边是七个安装click事件监听函数的例子。

div.addEventListener("click", function( event ) {
  // 显示在该节点,鼠标连续点击的次数
  event.target.innerHTML = "click count: " + event.detail;
}, false);

上面包车型大巴代码是利用click事件进行CSKugaF攻击(Cross-site request
forgery)的八个例证。

<a href="http://www.harmless.com/" onclick="
  var f = document.createElement('form');
  f.style.display = 'none';
  this.parentNode.appendChild(f);
  f.method = 'POST';
  f.action = 'http://www.example.com/account/destroy';
  f.submit();
  return false;">伪装的链接</a>

(2)dblclick事件

dblclick事件当顾客在elementdocumentwindow指标上,双击鼠标时触发。该事件会在mousedownmouseupclick未来触发。

(3)mouseup事件,mousedown事件

mouseup事件在自由按下的鼠标键时触发。

mousedown事件在按下鼠标键时接触。

(4)mousemove事件

mousemove事件当鼠标在贰个节点内部移动时接触。当鼠标持续运动时,该事件会接二连三触发。为了制止性能难点,建议对该事件的监听函数做一些范围,举例限定一段时间内只好运转一遍代码。

(5)mouseover事件,mouseenter事件

mouseover事件和mouseenter事件,都是鼠标步向多少个节点时接触。

双面的区分是,mouseover事件会冒泡,mouseenter事件不会。子节点的mouseover事件会冒泡到父节点,进而触发父节点的mouseover事件。mouseenter事件就从不这种效能,所以走入子节点时,不会触发父节点的监听函数。

上边包车型客车事例是mouseenter事件与mouseover事件的界别。

// HTML代码为
// <ul id="test">
//   <li>item 1</li>
//   <li>item 2</li>
//   <li>item 3</li>
// </ul>

var test = document.getElementById("test");

// 进入test节点以后,该事件只会触发一次
test.addEventListener("mouseenter", function( event ) {
  event.target.style.color = "purple";
  setTimeout(function() {
    event.target.style.color = "";
  }, 500);
}, false);

// 接入test节点以后,只要在子Element节点上移动,该事件会触发多次
test.addEventListener("mouseover", function( event ) {
  event.target.style.color = "orange";
  setTimeout(function() {
    event.target.style.color = "";
  }, 500);
}, false);

地点代码中,由于mouseover事件会冒泡,所以子节点的mouseover事件会触发父节点的监听函数。

(6)mouseout事件,mouseleave事件

mouseout事件和mouseleave事件,都以鼠标离开七个节点时接触。

两岸的分别是,mouseout事件会冒泡,mouseleave事件不会。子节点的mouseout事件会冒泡到父节点,进而触发父节点的mouseout事件。mouseleave事件就从不这种效果与利益,所以离开子节点时,不会触发父节点的监听函数。

(7)contextmenu

contextmenu事件在贰个节点上点击鼠标右键时接触,也许按下“上下文菜单”键时触发。

MouseEvent对象

鼠标事件接受MouseEvent对象表示,它世襲UIEvent对象和Event对象。浏览器提供二个Mouse伊芙nt布局函数,用于新建二个MouseEvent实例。

event = new MouseEvent(typeArg, mouseEventInit);

MouseEvent布局函数的首先个参数是事件名称(或许的值富含click、mousedown、mouseup、mouseover、mousemove、mouseout),第叁个参数是多个风浪初叶化对象。该目的足以安顿以下属性。

  • screenX,设置鼠标相对于显示器的程度坐标(但不会移动鼠标),默以为0,等同于MouseEvent.screenX属性。
  • screenY,设置鼠标绝对于显示器的垂直坐标,默感到0,等同于Mouse伊芙nt.screenY属性。
  • clientX,设置鼠标相对于窗口的水准坐标,默以为0,等同于MouseEvent.clientX属性。
  • clientY,设置鼠标相对于窗口的垂直坐标,暗中同意为0,等同于MouseEvent.clientY属性。
  • ctrlKey,设置是或不是按下ctrl键,默以为false,等同于Mouse伊夫nt.ctrlKey属性。
  • shiftKey,设置是不是按下shift键,默感觉false,等同于Mouse伊芙nt.shiftKey属性。
  • altKey,设置是还是不是按下alt键,默以为false,等同于MouseEvent.altKey属性。
  • metaKey,设置是还是不是按下meta键,默以为false,等同于MouseEvent.metaKey属性。
  • button,设置按下了哪一个鼠标开关,默以为0。-1意味着从没按钮,0意味按下主键(日常是左键),1意味按下帮助键(经常是中档的键),2象征按后一次要键(常常是右键)。
  • buttons,设置按下了鼠标哪些键,是三个3个比特位的二进制值,默以为0。1代表按下主键(平常是左键),2意味着按下次要键(经常是右键),4意味按下援助键(平时是中档的键)。
  • relatedTarget,设置贰个Element节点,在mouseenter和mouseover事件时,表示鼠标刚刚离开的特别Element节点,在mouseout和mouseleave事件时,表示鼠标正在走入的极其Element节点。默以为null,等同于MouseEvent.relatedTarget属性。

以下属性也是可配备的,都卫冕自UIEvent布局函数和Event构造函数。

  • bubbles,布尔值,设置事件是还是不是冒泡,默以为false,等同于伊芙nt.bubbles属性。
  • cancelable,布尔值,设置事件是还是不是可收回,默认为false,等同于Event.cancelable属性。
  • view,设置事件的视图,经常是window或document.defaultView,等同于Event.view属性。
  • detail,设置鼠标点击的次数,等同于Event.detail属性。

上面是四个事例。

function simulateClick() {
  var event = new MouseEvent('click', {
    'bubbles': true,
    'cancelable': true
  });
  var cb = document.getElementById('checkbox');
  cb.dispatchEvent(event);
}

地点代码生成三个鼠标点击事件,并触发该事件。

以下介绍Mouse伊夫nt实例的质量。

altKey,ctrlKey,metaKey,shiftKey

以下属性重回二个布尔值,表示鼠标事件产生时,是或不是按下有些键。

  • altKey属性:alt键
  • ctrlKey属性:key键
  • metaKey属性:Meta键(Mac键盘是叁个四瓣的小花,Windows键盘是Windows键)
  • shiftKey属性:Shift键

// HTML代码为
// <body onclick="showkey(event);">

function showKey(e){
  console.log("ALT key pressed: " + e.altKey);
  console.log("CTRL key pressed: " + e.ctrlKey);
  console.log("META key pressed: " + e.metaKey);
  console.log("SHIFT key pressed: " + e.shiftKey);
}

上边代码中,点击网页会输出是不是还要按下Alt键。

button,buttons

以下属性重临事件的鼠标键信息。

(1)button

button属性重回叁个数值,表示按下了鼠标哪个键。

  • -1:未有按下键。
  • 0:按下主键(平常是左键)。
  • 1:按下扶持键(日常是中键只怕滚轮键)。
  • 2:按后一次键(平常是右键)。

// HTML代码为
// <button onmouseup="whichButton(event);">点击</button>

var whichButton = function (e) {
  switch (e.button) {
    case 0:
      console.log('Left button clicked.');
      break;
    case 1:
      console.log('Middle button clicked.');
      break;
    case 2:
      console.log('Right button clicked.');
      break;
    default:
      console.log('Unexpected code: ' + e.button);
  }
}

(2)buttons

buttons属性再次回到叁个3个比特位的值,表示还要按下了什么键。它用来管理同一时候按下七个鼠标键的事态。

  • 1:二进制为001,表示按下左键。
  • 2:二进制为010,表示按下右键。
  • 4:二进制为100,表示按下中键或滚轮键。

况兼按下多少个键的时候,种种按下的键对应的比特位都会有值。譬喻,同期按下左键和右键,会回去3(二进制为011)。

clientX,clientY,movementX,movementY,screenX,screenY

以下属性与事件之处相关。

(1)clientX,clientY

clientX属性再次回到鼠标地点相对于浏览器窗口左上角的程度坐标,单位为像素,与页面是或不是横向滚动无关。

clientY属性重返鼠标地点相对于浏览器窗口左上角的垂直坐标,单位为像素,与页面是还是不是纵向滚动毫不相关。

// HTML代码为
// <body onmousedown="showCoords(event)">

function showCoords(evt){
  console.log(
    "clientX value: " + evt.clientX + "n" +
    "clientY value: " + evt.clientY + "n"
  );
}

(2)movementX,movementY

movementX属性再次来到二个程度位移,单位为像素,表示这段日子岗位与上二个mousemove事件时期的品位间距。在数值上,等于current伊芙nt.movementX
= currentEvent.screenX – previous伊芙nt.screenX。

movementY属性重回叁个垂直位移,单位为像素,表示这两天岗位与上贰个mousemove事件之间的垂直间距。在数值上,等于current伊芙nt.movementY
= current伊夫nt.screenY – previousEvent.screenY。

(3)screenX,screenY

screenX属性重返鼠标地点相对于显示器左上角的品位坐标,单位为像素。

screenY属性重临鼠标地点绝对于显示器左上角的垂直坐标,单位为像素。

// HTML代码为
// <body onmousedown="showCoords(event)">

function showCoords(evt){
  console.log(
    "screenX value: " + evt.screenX + "n"
    + "screenY value: " + evt.screenY + "n"
  );
}

relatedTarget

relatedTarget属性重回事件的附带相关节点。对于那多少个从没次要相关节点的事件,该属性重回null。

下表列出分裂事件的target属性和relatedTarget属性含义。

事件名称 target属性 relatedTarget属性
focusin 接受焦点的节点 丧失焦点的节点
focusout 丧失焦点的节点 接受焦点的节点
mouseenter 将要进入的节点 将要离开的节点
mouseleave 将要离开的节点 将要进入的节点
mouseout 将要离开的节点 将要进入的节点
mouseover 将要进入的节点 将要离开的节点
dragenter 将要进入的节点 将要离开的节点
dragexit 将要离开的节点 将要进入的节点

上边是一个事例。

// HTML代码为
// <div id="outer" style="height:50px;width:50px;border-width:1px solid black;">
//   <div id="inner" style="height:25px;width:25px;border:1px solid black;"></div>
// </div>

var inner = document.getElementById("inner");

inner.addEventListener("mouseover", function (){
  console.log('进入' + event.target.id + " 离开" + event.relatedTarget.id);
});
inner.addEventListener("mouseenter", function (){
  console.log('进入' + event.target.id + " 离开" + event.relatedTarget.id);
});
inner.addEventListener("mouseout", function (){
  console.log('离开' + event.target.id + " 进入" + event.relatedTarget.id);
});
inner.addEventListener("mouseleave", function (){
  console.log('离开' + event.target.id + " 进入" + event.relatedTarget.id);
});

// 鼠标从outer进入inner,输出
// 进入inner 离开outer
// 进入inner 离开outer

// 鼠标从inner进入outer,输出
// 离开inner 进入outer
// 离开inner 进入outer

wheel事件

wheel事件是与鼠标滚轮相关的事件,近来独有叁个wheel事件。客商滚动鼠标的滚轮,就接触这一个事件。

该事件除了继续了Mouse伊芙nt、UI伊夫nt、伊芙nt的性情,还应该有多少个和睦的属性。

  • deltaX:再次回到五个数值,表示滚轮的水准滚动量。
  • deltaY:重回三个数值,表示滚轮的垂直滚动量。
  • deltaZ:重返二个数值,表示滚轮的Z轴滚动量。
  • deltaMode:重返叁个数值,表示滚动的单位,适用于地点二日性子。0表示像素,1象征行,2象征页。

浏览器提供一个WheelEvent布局函数,能够用来扭转滚轮事件的实例。它接收五个参数,第叁个是事件名称,第二个是安插对象。

var syntheticEvent = new WheelEvent("syntheticWheel", {"deltaX": 4, "deltaMode": 0});

键盘事件

键盘事件用来说述键盘行为,重要有keydown、keypress、keyup八个事件。

  • keydown:按下键盘时触发该事件。

  • keypress:只要按下的键并不是Ctrl、Alt、Shift和Meta,就任何时候触发keypress事件。

  • keyup:放手键盘时触发该事件。

下边是一个例证,对文本框设置keypress监听函数,只允许输入数字。

// HTML代码为
// <input type="text"
//   name="myInput"
//   onkeypress="return numbersOnly(this, event);"
//   onpaste="return false;"
// />

function numbersOnly(oToCheckField, oKeyEvent) {
  return oKeyEvent.charCode === 0
    || /d/.test(String.fromCharCode(oKeyEvent.charCode));
}

若是客商向来开关不松手,就能接连触发键盘事件,触发的相继如下。

  1. keydown
  2. keypress
  3. keydown
  4. keypress
  5. (重复以上过程)
  6. keyup

键盘事件采用Keyboard伊芙nt对象表示,该目标世袭了UIEvent和Mouse伊夫nt对象。浏览器提供Keyboard伊芙nt布局函数,用来新建键盘事件的实例。

event = new KeyboardEvent(typeArg, KeyboardEventInit);

KeyboardEvent布局函数的率先个参数是三个字符串,表示事件类型,第一个参数是一个事件配置对象,可计划以下字段。

  • key,对应KeyboardEvent.key属性,默以为空字符串。
  • ctrlKey,对应KeyboardEvent.ctrlKey属性,默认为false。
  • shiftKey,对应KeyboardEvent.shiftKey属性,默认为false。
  • altKey,对应KeyboardEvent.altKey属性,默认为false。
  • metaKey,对应KeyboardEvent.metaKey属性,默认为false。

上面便是KeyboardEvent实例的习性介绍。

altKey,ctrlKey,metaKey,shiftKey

以下属性再次回到一个布尔值,表示是不是按下相应的键。

  • altKey:alt键
  • ctrlKey:ctrl键
  • metaKey:meta键(mac系统是三个四瓣的小花,windows系统是windows键)
  • shiftKey:shift键

function showChar(e){
  console.log("ALT: " + e.altKey);
  console.log("CTRL: " + e.ctrlKey);
  console.log("Meta: " + e.metaKey);
  console.log("Meta: " + e.shiftKey);
}

key,charCode

key属性再次回到三个字符串,表示按下的键名。若是同期按下一个调控键和三个符号键,则赶回符号键的键名。比方,按下Ctrl+a,则重返a。假使不恐怕识别键名,则赶回字符串Unidentified。

尤为重要作用键的键名(不一样的浏览器可能大相径庭):Backspace,Tab,Enter,Shift,Control,Alt,CapsLock,CapsLock,Esc,Spacebar,PageUp,PageDown,End,Home,Left,Right,Up,Down,PrintScreen,Insert,Del,Win,F1~F12,NumLock,Scroll等。

charCode属性重回叁个数值,表示keypress事件按钮的Unicode值,keydown和keyup事件不提供这几个天性。注意,该属性已经从正规移除,即便浏览器还扶植,但应当尽可能不应用。

速度事件

速度事件用来描述一个事变进展的过程,举个例子XMLHttpRequest对象发出的HTTP必要的进度、<img>、<audio>、<video>、<style>、<link>加载外界能源的历程。下载和上传都会时有爆发进程事件。

速度事件有以下三种。

  • abort事件:当进程事件被暂停时接触。要是产生错误,引致进度中止,不会触发该事件。

  • error事件:由于错误以致能源超级小概加载时接触。

  • load事件:进程成功结束时接触。

  • loadstart事件:进程带头时接触。

  • loadend事件:进程结束时接触,发生顺序排在error事件abort事件load事件背后。

  • progress事件:当操作处于进程之中,由传输的数据块不断触发。

  • timeout事件:进度超过限制期限触及。

image.addEventListener('load', function(event) {
  image.classList.add('finished');
});

image.addEventListener('error', function(event) {
  image.style.display = 'none';
});

上边代码在图纸成分加载成功后,为图片成分的class属性增加四个值“finished”。假诺加载退步,就把图纸成分的体制设置为不出示。

有的时候候,图片加载会在本子运营此前就完了,特别是当脚本放置在网页尾部的时候,因而有望使得load和error事件的监听函数根本不会被施行。所以,相比较可靠的格局,是用complete属性先决断一下是或不是加载成功。

function loaded() {
  // code after image loaded
}

if (image.complete) {
  loaded();
} else {
  image.addEventListener('load', loaded);
}

出于DOM未有提供像complete属性那样的,判定是或不是发生加载错误的性质,所以error事件的监听函数最佳放在img成分的HTML属性中,那样技艺承保产生加载错误时百分之百会实施。

<img src="/wrong/url" onerror="this.style.display='none';" />

error事件有多个特别的习性,正是不会冒泡。那样的设计是科学的,防止引发父成分的error事件监听函数。

进度事件选拔ProgressEvent对象表示。Progress伊芙nt实例有以下属性。

  • lengthComputable:重返一个布尔值,表示这两天速度是还是不是有所可总计的长短。借使为false,就象征近年来行度不能够度量。

  • total:重回四个数值,表示目前行度的总参谋长度。若是是由此HTTP下载有些能源,表示内容本身的尺寸,不含HTTP底部的长短。如果lengthComputable属性为false,则total属性就不能获得正确的值。

  • loaded:重临贰个数值,表示这两天行度已经做到的数量。该属性除以total属性,就能够赢得前段时间速度的比重。

上面是一个事例。

var xhr = new XMLHttpRequest();

xhr.addEventListener("progress", updateProgress, false);
xhr.addEventListener("load", transferComplete, false);
xhr.addEventListener("error", transferFailed, false);
xhr.addEventListener("abort", transferCanceled, false);

xhr.open();

function updateProgress (e) {
  if (e.lengthComputable) {
    var percentComplete = e.loaded / e.total;
  } else {
    console.log('不能计算进度');
  }
}

function transferComplete(e) {
  console.log('传输结束');
}

function transferFailed(evt) {
  console.log('传输过程中发生错误');
}

function transferCanceled(evt) {
  console.log('用户取消了传输');
}

loadend事件的监听函数,能够用来顶替abort事件/load事件/error事件的监听函数。

req.addEventListener("loadend", loadEnd, false);

function loadEnd(e) {
  console.log('传输结束,成功失败未知');
}

loadend事件自己不提供有关进度甘休的因由,但足以用它来做有所进度甘休场景都须求做的部分操作。

其它,上边是下载进度的进度事件,还设有上传进度的进程事件。那时全数监听函数都要放在XMLHttpRequest.upload对象方面。

var xhr = new XMLHttpRequest();

xhr.upload.addEventListener("progress", updateProgress, false);
xhr.upload.addEventListener("load", transferComplete, false);
xhr.upload.addEventListener("error", transferFailed, false);
xhr.upload.addEventListener("abort", transferCanceled, false);

xhr.open();

浏览器提供八个Progress伊夫nt构造函数,用来生成速度事件的实例。

progressEvent = new ProgressEvent(type, {
  lengthComputable: aBooleanValue,
  loaded: aNumber,
  total: aNumber
});

上边代码中,Progress伊夫nt构造函数的首先个参数是事件类型(字符串),第1个参数是陈设对象,用来钦赐lengthComputable属性(私下认可值为false)、loaded属性(暗中同意值为0)、total属性(暗许值为0)。

拖沓事件

拖沓指的是,客商在有个别对象上按下鼠标键不放,拖动它到另五个地方,然后释放鼠标键,将该对象放在此。

拖沓的指标有少数种,包罗Element节点、图片、链接、选中的文字等等。在HTML网页中,除了Element节点私下认可不得以拖沓,别的(图片、链接、选中的文字)都以能够直接拖拖拉拉的。为了让Element节点可拖拖拉拉,能够将该节点的draggable属性设为true。

<div draggable="true">
  此区域可拖拉
</div>

draggable属性可用来任何Element节点,可是图片(img成分)和链接(a成分)不加这些天性,就可以拖沓。对于它们,用到那个脾性的时候,往往是将其设为false,幸免拖拖拉拉。

只顾,一旦某些Element节点的draggable属性设为true,就无法再用鼠标选中该节点内部的文字或子节点了。

事件种类

当Element节点或选中的文本被拖拖沓沓时,就能够不停触发拖拖拉拉事件,富含以下一些事件。

  • drag事件:拖沓进度中,在被拖沓的节点上连发触发。

  • dragstart事件:拖拖沓沓启幕时在被拖沓的节点上接触,该事件的target属性是被拖拖沓沓的节点。日常应该在这里个事件的监听函数中,内定拖沓的数码。

  • dragend事件:拖拖拉拉完工作时间(释放鼠标键或按下escape键)在被拖拖沓沓的节点上接触,该事件的target属性是被拖拖沓沓的节点。它与dragStart事件,在同三个节点上接触。不管拖拖拉拉是或不是跨窗口,大概中途被注销,dragend事件三番三遍会触发的。

  • dragenter事件:拖沓踏向当前节点时,在当前节点上接触,该事件的target属性是时下节点。平时应该在此个事件的监听函数中,钦定是还是不是同意在时下节点放下(drop)拖沓的数量。要是当前节点未有该事件的监听函数,恐怕监听函数不试行其余操作,就表示不容许在最近节点放下数据。在视觉上显得拖沓跻身当前节点,也是在这里个事件的监听函数中安装。

  • dragover事件:拖拖沓沓到日前节点最上部时,在日前节点上穿梭触发,该事件的target属性是这两天节点。该事件与dragenter事件基本贴近,暗中认可会重新载入参数当前的拖拖沓沓事件的职能(DataTransfer对象的dropEffect属性)为none,即不一致敬放下被拖沓的节点,所以一旦允许在那个时候此刻节点drop数据,平时会接收preventDefault方法,撤废重新初始化拖拖拉拉效果为none。

  • dragleave事件:拖拖沓沓离开当前节点范围时,在时下节点上接触,该事件的target属性是当下节点。在视觉上海展览中心示拖沓离开当前节点,就在这里个事件的监听函数中装置。

  • drop事件:被拖拖沓沓的节点或选中的文本,释放到对象节点时,在目的节点上接触。注意,就算当前节点不准drop,纵然在该节点上方松开鼠标键,也不会触发该事件。假若客商按下Escape键,撤除这几个操作,也不会触发该事件。该事件的监听函数担当抽出拖拖拉拉数量,并实行有关管理。

至于拖沓风浪,有以下几点注意事项。

  • 拖拖拉拉经过只触发以上那几个拖拖沓沓事件,纵然鼠标在移动,然则鼠标事件不会触发。

  • 将文件从操作系统拖拖拉拉进浏览器,不会触发dragStart和dragend事件。

  • dragenter和dragover事件的监听函数,用来钦赐能够放下(drop)拖沓的数码。由于网页的大好多区域不相符充作drop的对象节点,所以那七个事件的暗中认可设置为眼下节点不容许drop。借使想要在对象节点上drop拖沓的多寡,首先必得遏止那三个事件的私下认可行为,只怕吊销那多个事件。

<div ondragover="return false">
<div ondragover="event.preventDefault()">

地方代码中,如若不撤废拖拖沓沓事件依旧阻止暗中同意行为,就不容许在div节点上drop被拖拖拉拉的节点。

拖沓事变用一个Drag伊芙nt对象表示,该目的世襲Mouse伊芙nt对象,因而也就持续了UI伊芙nt和伊芙nt对象。DragEvent对象独有叁个独有的习性DataTransfer,别的都以连续的天性。DataTransfer属性用来读写拖沓事件中传输的数码,详见下文《DataTransfer对象》的一部分。

下边包车型地铁例子展示,怎么着动态改造被拖动节点的背景观。

div.addEventListener("dragstart", function(e) {
  this.style.backgroundColor = "red";
}, false);
div.addEventListener("dragend", function(e) {
  this.style.backgroundColor = "green";
}, false);

地方代码中,div节点被拖动时,背景象会变为钴黄,拖动甘休,又变回日光黄。

上面是二个事例,展现怎么落到实处将二个节点从脚下父节点,拖拖拉拉到另一个父节点中。

// HTML代码为
// <div class="dropzone">
//    <div id="draggable" draggable="true">
//       该节点可拖拉
//    </div>
// </div>
// <div class="dropzone"></div>
// <div class="dropzone"></div>
// <div class="dropzone"></div>

// 被拖拉节点
var dragged;

document.addEventListener("dragstart", function( event ) {
  // 保存被拖拉节点
  dragged = event.target;
  // 被拖拉节点的背景色变透明
  event.target.style.opacity = 0.5;
  // 兼容Firefox
  event.dataTransfer.setData('text/plain', 'anything');
}, false);

document.addEventListener('dragend', function( event ) {
  // 被拖拉节点的背景色恢复正常
  event.target.style.opacity = '';
}, false);

document.addEventListener('dragover', function( event ) {
  // 防止拖拉效果被重置,允许被拖拉的节点放入目标节点
  event.preventDefault();
}, false);

document.addEventListener('dragenter', function( event ) {
  // 目标节点的背景色变紫色
  // 由于该事件会冒泡,所以要过滤节点
  if ( event.target.className == 'dropzone' ) {
    event.target.style.background = 'purple';
  }
}, false);

document.addEventListener('dragleave', function( event ) {
  // 目标节点的背景色恢复原样
  if ( event.target.className == 'dropzone' ) {
    event.target.style.background = "";
  }
}, false);

document.addEventListener('drop', function( event ) {
  // 防止事件默认行为(比如某些Elment节点上可以打开链接)
  event.preventDefault();
  if ( event.target.className === 'dropzone' ) {
    // 恢复目标节点背景色
    event.target.style.background = '';
    // 将被拖拉节点插入目标节点
    dragged.parentNode.removeChild( dragged );
    event.target.appendChild( dragged );
  }
}, false);

DataTransfer对象概述

负有的拖拉事件皆有二个dataTransfer属性,用来保存须要传递的数码。这一个天性的值是叁个DataTransfer对象。

拖拖拉拉的数目保存两地方的数码:数据的品种(又称格式)和数码的值。数据的花色是二个MIME字符串,比方text/plain可能image/jpeg,数据的值是一个字符串。日常的话,假使拖拖沓沓一段文本,则数据默许正是这段文本;如若拖拖沓沓四个链接,则数据暗中同意就是链接的U帕杰罗L。

当拖沓事件初步的时候,能够提供数据类型和数据值;在拖拖拉拉进度中,通过dragenter和dragover事件的监听函数,检查数据类型,以鲜明是否允许放下(drop)被拖拖沓沓的对象。比方,在只允许放下链接的区域,检查拖拖沓沓的数据类型是不是为text/uri-list。

发出drop事件时,监听函数抽取拖沓的数码,对其进展管理。

DataTransfer对象的性质

DataTransfer对象有以下属性。

(1)dropEffect

dropEffect属性设寄放下(drop)被拖沓节点时的机能,大概的值包罗copy(复制被拖沓的节点)、move(移动被拖拖拉拉的节点)、link(创设指向被拖拖拉拉的节点的链接)、none(不能够放下被拖拖拉拉的节点)。设置除此以外的值,都以不著见到效果的。

target.addEventListener('dragover', function(e) {
  e.preventDefault();
  e.stopPropagation();
  e.dataTransfer.dropEffect = 'copy';
});

dropEffect属性日常在dragenter和dragover事件的监听函数中设置,对于dragstart、drag、dragleave那五个事件,该属性不起效率。步入指标节点后,拖拖沓沓一颦一笑会初叶化成客商设定的效应,客商能够通过按下Shift键和Control键,修正始于设置,在copy、move、link三种作用中切换。

鼠标箭头会基于dropEffect属性改造造型,提醒这段时间正处在哪一类作用。那代表,通过鼠标就能够判定是还是不是足以在时下节点drop被拖沓的节点。

(2)effectAllowed

effectAllowed属性设置这一次拖拖拉拉中允许的意义,恐怕的值包涵copy(复制被拖沓的节点)、move(移动被拖拖沓沓的节点)、link(创设指向被拖沓节点的链接)、copyLink(允许copy或link)、copyMove(允许copy或move)、linkMove(允许link或move)、all(允许持有机能)、none(无法放下被拖拖拉拉的节点)、uninitialized(私下认可值,等同于all)。倘若某种意义是不容许的,客户就不可能在对象节点中达到这种功效。

dragstart事件的监听函数,能够安装被拖沓节点允许的成效;dragenter和dragover事件的监听函数,能够设置指标节点允许的效果与利益。

event.dataTransfer.effectAllowed = "copy";

dropEffect属性和effectAllowed属性,往往协作使用。

event.dataTransfer.effectAllowed = "copyMove";
event.dataTransfer.dropEffect = "copy";

地点代码中,copy是点名的作用,可是足以因此Shift或Ctrl键(依照平台而定),将成效切换到move。

假使dropEffect属性和effectAllowed属性之中,有叁个为none,就不恐怕在对象节点上形成drop操作。

(3)files

files属性是一个FileList对象,包括一组当半夏件,能够用来在拖拖沓沓操作中传递。假如本次拖拖拉拉不关乎文件,则属性为空的FileList对象。

上面正是贰个收受拖拖拉拉文件的事例。

// HTML代码为
// <div id="output" style="min-height: 200px;border: 1px solid black;">
//   文件拖拉到这里
// </div>

var div = document.getElementById('output');

div.addEventListener("dragenter", function( event ) {
  div.textContent = '';
  event.stopPropagation();
  event.preventDefault();
}, false);

div.addEventListener("dragover", function( event ) {
  event.stopPropagation();
  event.preventDefault();
}, false);

div.addEventListener("drop", function( event ) {
  event.stopPropagation();
  event.preventDefault();
  var files = event.dataTransfer.files;
  for (var i = 0; i < files.length; i++) {
    div.textContent += files[i].name + ' ' + files[i].size + '字节n';
  }
}, false);

上面代码中,通过files属性读取拖Lavin件的信息。假设想要读取文件内容,将在动用FileReader对象。

div.addEventListener('drop', function(e) {
  e.preventDefault();
  e.stopPropagation();

  var fileList = e.dataTransfer.files;
  if (fileList.length > 0) {
    var file = fileList[0];
    var reader = new FileReader();
    reader.onloadend = function(e) {
      if (e.target.readyState == FileReader.DONE) {
        var content = reader.result;
        contentDiv.innerHTML = "File: " + file.name + "nn" + content;
      }
    }
    reader.readAsBinaryString(file);
  }
});

(4)types

types属性是多少个数组,保存每三遍拖拖沓沓的多寡格式,例如拖Lavin件,则格式新闻就为File。

上边是一个例子,通过检查dataTransfer属性的品类,决定是或不是同意在当前节点实践drop操作。

function contains(list, value){
  for( var i = 0; i < list.length; ++i ){
    if(list[i] === value) return true;
  }
  return false;
}

function doDragOver(event){
  var isLink = contains( event.dataTransfer.types, "text/uri-list");
  if (isLink) event.preventDefault();
}

地方代码中,独有当被拖拖沓沓的节点是多少个链接时,才允许在现阶段节点放下。

DataTransfer对象的法子

DataTransfer对象有以下方法。

(1)setData()

setData方法用来安装事件所包蕴的钦命项目标多寡。它担负五个参数,第叁个是数据类型,第叁个是实际数额。假使钦赐的品类在现成数量中空头支票,则该类型将写入types属性;若是已经存在,在该项指标存活数量将被沟通。

event.dataTransfer.setData("text/plain", "Text to drag");

地点代码为事件到场纯文本格式的数量。

假若拖Lavin本框可能拖拖拉拉选中的文本,会私下认可将文件数据增加到dataTransfer属性,不用手动钦命。

<div draggable="true" ondragstart="
  event.dataTransfer.setData('text/plain', 'bbb')">
  aaa
</div>

地点代码中,拖拖拉拉数码实际上是bbb,并非aaa。

上面是加多其余项指标多寡。由于text/plain是最多如牛毛协助的格式,为了保障宽容性,提议最终总是将数据保存一份纯文本的格式。

var dt = event.dataTransfer;

// 添加链接
dt.setData("text/uri-list", "http://www.example.com");
dt.setData("text/plain", "http://www.example.com");
// 添加HTML代码
dt.setData("text/html", "Hello there, <strong>stranger</strong>");
dt.setData("text/plain", "Hello there, <strong>stranger</strong>");
// 添加图像的URL
dt.setData("text/uri-list", imageurl);
dt.setData("text/plain", imageurl);

能够二次提供各类格式的多少。

var dt = event.dataTransfer;
dt.setData("application/x-bookmark", bookmarkString);
dt.setData("text/uri-list", "http://www.example.com");
dt.setData("text/plain", "http://www.example.com");

地方代码中,通过在同三个风浪方面,寄放三体系型的多少,使得拖沓事件能够在区别的靶子方面,drop区别的值。注意,第一种格式是叁个自定义格式,浏览器暗中同意不能够读取,那象征,唯有有些安排了特定代码的节点,才大概drop(读取到)那个数据。

(2)getData()

getData方法采取四个字符串(表示数据类型)作为参数,再次回到事件所带的内定项目标数码(经常是用setData方法增加的数额)。假若钦赐项目标多少不设有,则赶回空字符串。经常独有drop事件触发后,才具抽取数据。借使抽出另三个域名存放的数据,将会报错。

上面是二个drop事件的监听函数,用来抽出钦定项目的多寡。

function onDrop(event){
  var data = event.dataTransfer.getData("text/plain");
  event.target.textContent = data;
  event.preventDefault();
}

下边代码收取拖拖拉拉事件的文书数据,将其替换来当前节点的文本内容。注意,那时候还非得撤回浏览器的默许行为,因为假设客商拖拖拉拉的是贰个链接,浏览器默许会在方今窗口展开这几个链接。

getData方法再次回到的是多个字符串,若是内部包蕴多项数据,就亟须手动深入分析。

function doDrop(event){
  var lines = event.dataTransfer.getData("text/uri-list").split("n");
  for (let line of lines) {
    let link = document.createElement("a");
    link.href = line;
    link.textContent = line;
    event.target.appendChild(link);
  }
  event.preventDefault();
}

地方代码中,getData方法再次来到的是一组链接,就不得不自行拆解深入分析。

类型值钦点为UENVISIONL,能够收取第贰个有效链接。

var link = event.dataTransfer.getData("URL");

上面是二回性收取七类别型的数量。

function doDrop(event){
  var types = event.dataTransfer.types;
  var supportedTypes = ["text/uri-list", "text/plain"];
  types = supportedTypes.filter(function (value) types.includes(value));
  if (types.length)
    var data = event.dataTransfer.getData(types[0]);
  event.preventDefault();
}

(3)clearData()

clearData方法选拔三个字符串(表示数据类型)作为参数,删除事件所带的钦点项指标数据。若无一点点名项目,则删除全数数据。要是钦点项目一纸空文,则原数据不受影响。

event.dataTransfer.clearData("text/uri-list");

地点代码解除事件所带的ULX570L数据。

(4)setDragImage()

拖动进程中(dragstart事件触发后),浏览器会呈现一张图纸跟随鼠标一同活动,表示被拖动的节点。那张图片是半自动成立的,平时显示为被拖动节点的外观,无需团结动手设置。setDragImage方法能够用来自定义那张图纸,它担当四个参数,第贰个是img图片成分也许canvas成分,就算轻便或为null则运用被拖动的节点的外观,第二个和第多少个参数为鼠标相对于该图形左上角的横坐标和右坐标。

上边是三个例证。

// HTML代码为
// <div id="drag-with-image" class="dragdemo" draggable="true">
     drag me
// </div>

var div = document.getElementById("drag-with-image");
div.addEventListener("dragstart", function(e) {
  var img = document.createElement("img");
  img.src = "http://path/to/img";
  e.dataTransfer.setDragImage(img, 0, 0);
}, false);

触摸事件

触摸API由多个指标组成。

  • Touch
  • TouchList
  • TouchEvent

Touch对象表示触摸点(一根手指只怕一根触摸笔),用来陈诉触摸动作,富含地点、大小、形状、压力、目的成分等性能。有的时候,触摸动作由多个触摸点(多根手指或然多根触摸笔)组成,八个触摸点的集结由TouchList对象表示。TouchEvent对象表示由触摸引发的平地风波,独有触摸屏才会掀起这一类事件。

不少时候,触摸事件和鼠标事件同期触发,即便这时候并不曾用到鼠标。那是为着让那多少个只定义鼠标事件、未有概念触摸事件的代码,在触摸屏的情形下照旧能用。假诺想幸免这种情状,能够用preventDefault方法阻碍发出鼠标事件。

Touch对象

Touch对象表示三个触摸点。触摸点或者是一根手指,也可能是一根触摸笔。它有以下属性。

(1)identifier

identifier属性表示Touch实例的独步的识别符。它在全路触摸进程中保持不改变。

var id = touchItem.identifier;

TouchList对象的identifiedTouch方法,能够依靠这一个性格,从八个集中里面抽出对应的Touch对象。

(2)screenX,screenY,clientX,clientY,pageX,pageY

screenX属性和screenY属性,分别表示触摸点相对于显示屏左上角的横坐标和纵坐标,与页面是还是不是滚动无关。

clientX属性和clientY属性,分别代表触摸点相对于浏览器视口左上角的横坐标和纵坐标,与页面是或不是滚动非亲非故。

pageX属性和pageY属性,分别代表触摸点相对于如今页面左上角的横坐标和纵坐标,包蕴了页面滚动带给的运动。

(3)radiusX,radiusY,rotationAngle

radiusX属性和radiusY属性,分别重返触摸点左近受到震慑的扁圆形范围的X轴和Y轴,单位为像素。

rotationAngle属性表示触摸区域的扁圆形的旋转角度,单位为度数,在0到90度之间。

下边那八个性情同盟定义了客商与显示屏接触的区域,对于描述手指这一类非准确的入手,很有帮衬。指尖接触荧屏,触摸范围会形成多个椭圆,那六特性子就用来呈报那些椭圆区域。

(4)force

force属性重回三个0到1里面包车型大巴数值,表示触摸压力。0代表未有压力,1意味着硬件所能识别的最大压力。

(5)target

target属性重回五个Element节点,代表触摸发生的极其节点。

TouchList对象

TouchList对象是四个像样数组的对象,成员是与有些触摸事件相关的享有触摸点。比如,客户用三根手指触摸,产生的TouchList对象就有多少个分子,每根手指对应一个Touch对象。

TouchList实例的length属性,重回TouchList对象的分子数量。

TouchList实例的identifiedTouch方法和item方法,分别选用id属性和索引值(从0最先)作为参数,抽取钦点的Touch对象。

TouchEvent对象

TouchEvent对象世襲Event对象和UI伊芙nt对象,表示触摸引发的风云。除了被一连的性质以外,它还大概有部分温馨的习性。

(1)键盘相关属性

以下属性都为只读属性,再次回到三个布尔值,表示触摸的还要,是还是不是按下有个别键。

  • altKey 是还是不是按下alt键
  • ctrlKey 是还是不是按下ctrl键
  • metaKey 是或不是按下meta键
  • shiftKey 是或不是按下shift键

(2)changedTouches

changedTouches属性重临一个TouchList对象,包括了由近期触摸事件引发的具有Touch对象(即有关的触摸点)。

对此touchstart事件,它表示被激活的触摸点;对于touchmove事件,代表爆发变化的触摸点;对于touchend事件,代表未有的触摸点(即不再被触碰的点)。

var touches = touchEvent.changedTouches;

(3)targetTouches

targetTouches属性重回二个TouchList对象,满含了触摸的目的Element节点内部,全部照旧处在活动状态的触摸点。

var touches = touchEvent.targetTouches;

(4)touches

touches属性重返八个TouchList对象,满含了有着仍然处于活动状态的触摸点。

var touches = touchEvent.touches;

触摸事件的档期的顺序

触摸引发的平地风波,有以下几类。能够通过Touch伊芙nt.type属性,查看终归爆发的是哪种事件。

  • touchstart:顾客接触触摸屏时接触,它的target属性重回产生触摸的Element节点。

  • touchend:客商不再接触触摸屏时(只怕移出显示器边缘时)触发,它的target属性与touchstart事件的target属性是均等的,它的changedTouches属性再次来到多少个TouchList对象,包涵全部不再触摸的触摸点(Touch对象)。

  • touchmove:客户移动触摸点时接触,它的target属性与touchstart事件的target属性一致。即便入手的半径、角度、力度发生变化,也会触发该事件。

  • touchcancel:触摸点撤废时接触,譬喻在触摸区域跳出三个态度窗口(modal
    window)、触摸点离开了文档区域(步向浏览器菜单栏区域)、顾客放置越来越多的触摸点(自动打消早前的触摸点)。

上面是二个例证。

var el = document.getElementsByTagName("canvas")[0];
el.addEventListener("touchstart", handleStart, false);
el.addEventListener("touchmove", handleMove, false);

function handleStart(evt) {
  // 阻止浏览器继续处理触摸事件,
  // 也阻止发出鼠标事件
  evt.preventDefault();
  var touches = evt.changedTouches;

  for (var i = 0; i < touches.length; i++) {
    console.log(touches[i].pageX, touches[i].pageY);
  }
}

function handleMove(evt) {
  evt.preventDefault();
  var touches = evt.changedTouches;

  for (var i = 0; i < touches.length; i++) {
    var id = touches[i].identifier;
    var touch = touches.identifiedTouch(id);
    console.log(touch.pageX, touch.pageY);
  }
}

表单事件

Input事件,select事件,change事件

以下事件与表单成员的值变化有关。

(1)input事件

input事件当<input>、<textarea>的值发生变化时接触。别的,展开contenteditable属性的成分,只要值发生变化,也会触发input事件。

input事件的三个特征,正是会一连触发,比如客商每趟按下贰次开关,就能够接触二回input事件。

(2)select事件

select事件当在<input>、<textarea>中选普通话本时触发。

// HTML代码为
// <input id="test" type="text" value="Select me!" />

var elem = document.getElementById('test');
elem.addEventListener('select', function() {
  console.log('Selection changed!');
}, false);

(3)Change事件

Change事件当<input>、<select>、<textarea>的值爆发变化时接触。它与input事件的最大不一致,正是不会接连触发,独有当全部育高修改完毕时才会接触,并且input事件必然会抓住change事件。具体来讲,分成以下二种状态。

  • 激活单选框(radio)或复选框(checkbox)时接触。
  • 客户提交时接触。例如,从下列列表(select)完结选择,在日期或文件输入框完结选择。
  • 当文本框或textarea成分的值爆发改换,并且丧失关键时接触。

上边是一个事例。

// HTML代码为
// <select size="1" onchange="changeEventHandler(event);">
//   <option>chocolate</option>
//   <option>strawberry</option>
//   <option>vanilla</option>
// </select>

function changeEventHandler(event) {
  console.log('You like ' + event.target.value + ' ice cream.');
}

reset事件,submit事件

以下事件爆发在表单对象上,并非发生在表单的分子上。

(1)reset事件

reset事件当表单重新设置(全体表单成员变回私下认可值)时接触。

(2)submit事件

submit事件当表单数据向服务器交由时接触。注意,submit事件的发生对象是form成分,并不是button成分(即便它的档期的顺序是submit),因为提交的是表单,并非按键。

文档事件

beforeunload事件,unload事件,load事件,error事件,pageshow事件,pagehide事件

以下事件与网页的加载与卸载相关。

(1)beforeunload事件

beforeunload事件当窗口将在关闭,或然document和网页财富将在卸载时接触。它能够用来防卫客商不警惕关闭网页。

该事件的暗许动作正是关闭当前窗口或文书档案。假设在监听函数中,调用了event.preventDefault(),可能对事件目的的returnValue属性授予一个非空的值,就能自行跳出三个认同框,让客户确认是或不是关闭网页。假如客户点击“撤除”按键,网页就不会关闭。监听函数所重回的字符串,会来得在鲜明对话框之中。

window.onbeforeunload = function() {
  if (textarea.value != textarea.defaultValue) {
    return '你确认要离开吗?';
  }
};

上面代码表示,当客户关闭网页,会跳出三个承认对话框,上面显示“你承认要离开吗?”。

上边包车型客车三种写法,具备肖似效劳。

window.addEventListener('beforeunload', function( event ) {
  event.returnValue = '你确认要离开吗?';
});

// 等同于
window.addEventListener('beforeunload', function( event ) {
  event.preventDefault();
});

上边代码中,事件指标的returnValue属性的值,将会成为确认框的提示文字。

设若定义了beforeunload事件的监听函数,网页不会被浏览器缓存。

(2)unload事件

unload事件在窗口关闭或许document对象将在卸载时接触,产生在window、body、frameset等对象方面。它的接触顺序排在beforeunload、pagehide事件背后。unload事件只在页面未有被浏览器缓存时才会接触,换言之,假若由此按下“前行/后退”引致页面卸载,并不会触发unload事件。

当unload事件时有发生时,document对象处于二个特别情形。全体资源仍然留存,然则对客户来讲都不可以看到,UI相互影响(window.open、alert、confirm方法等)全体空头。此时纵然抛出错误,也不能够终止文书档案的卸载。

window.addEventListener('unload', function(event) {
  console.log('文档将要卸载');
});

譬喻在window对象上定义了该事件,网页就不会被浏览器缓存。

(3)load事件,error事件

load事件在页面加载成功时接触,error事件在页面加载败北时接触。注意,页面从浏览器缓存加载,并不会触发load事件。

那七个事件实际上归属进程事件,不仅仅发生在document对象,还发生在各类外界能源方面。浏览网页正是贰个加载各类财富的经过,图像(image)、样式表(style
sheet)、脚本(script)、摄像(video)、音频(audio)、Ajax央求(XMLHttpRequest)等等。这个资源和document对象、window对象、XMLHttpRequestUpload对象,都会触发load事件和error事件。

(4)pageshow事件,pagehide事件

私下认可景况下,浏览器会在现阶段对话(session)缓存页面,当顾客点击“前行/后退”开关时,浏览器就能够从缓存中加载页面。

pageshow事件在页面加载时接触,包含率先次加载和从缓存加载两种状态。假使要钦定页面每一趟加载(不管是否从浏览器缓存)时都运维的代码,能够放在此个事件的监听函数。

先是次加载时,它的触发顺序排在load事件背后。从缓存加载时,load事件不会接触,因为网页在缓存中的样子经常是load事件的监听函数运营后的规范,所以不要再一次试行。同理,借使是从缓存中加载页面,网页内初阶化的JavaScript脚本(比方DOMContentLoaded事件的监听函数)也不会实施。

window.addEventListener('pageshow', function(event) {
  console.log('pageshow: ', event);
});

pageshow事件有叁个persisted属性,重回二个布尔值。页面第二回加载时,那天本性是false;当页面从缓存加载时,那特性子是true。

window.addEventListener('pageshow', function(event){
  if (event.persisted) {
    // ...
  }
});

pagehide事件与pageshow事件相符,当顾客通过“前行/后退”按键,离开当前页面时接触。它与unload事件的界别在于,假如在window对象上定义unload事件的监听函数之后,页面不会保留在缓存中,而利用pagehide事件,页面会保存在缓存中。

pagehide事件的event对象有三个persisted属性,将以此性情设为true,就意味着页面要封存在缓存中;设为false,表示网页不保存在缓存中,这个时候假诺设置了unload事件的监听函数,该函数将在pagehide事件后当即运维。

若是页面满含frame或iframe成分,则frame页面包车型地铁pageshow事件和pagehide事件,都会在主页面在此之前接触。

DOMContentLoaded事件,readystatechange事件

以下事件与文档状态相关。

(1)DOMContentLoaded事件

当HTML文书档案下载并解析实现之后,就能在document对象上触发DOMContentLoaded事件。那时候,仅仅完结了HTML文书档案的分析(整张页面包车型大巴DOM生成),全体外界财富(样式表、脚本、iframe等等)恐怕还一贯不下载结束。也正是说,这么些事件比load事件,产生时间早得多。

document.addEventListener("DOMContentLoaded", function(event) {
  console.log("DOM生成");
});

瞩目,网页的JavaScript脚本是联合实施的,所以定义DOMContentLoaded事件的监听函数,应该放在全体脚本的最前边。不然脚本一旦爆发拥塞,将延迟触发DOMContentLoaded事件。

(2)readystatechange事件

readystatechange事件爆发在Document对象和XMLHttpRequest对象,当它们的readyState属性产生变化时接触。

document.onreadystatechange = function () {
  if (document.readyState == "interactive") {
    // ...
  }
}

IE8不扶助DOMContentLoaded事件,不过扶助那些事件。由此,能够利用readystatechange事件,在低版本的IE中代表DOMContentLoaded事件。

scroll事件,resize事件

以下事件与窗口行为有关。

(1)scroll事件

scroll事件在文档或文书档案成分滚动时接触。

由于该事件会一而再一而再地质大学方触及,所以它的监听函数之中不该有这个花费总结的操作。推荐的做法是选拔requestAnimationFrame或setTimeout调控该事件的触发频率,然后能够组成custom伊芙nt抛出贰个新事件。

(function() {
  var throttle = function(type, name, obj) {
    var obj = obj || window;
    var running = false;
    var func = function() {
      if (running) { return; }
      running = true;
      requestAnimationFrame(function() {
        obj.dispatchEvent(new CustomEvent(name));
        running = false;
      });
    };
    obj.addEventListener(type, func);
  };

  // 将scroll事件重定义为optimizedScroll事件
  throttle("scroll", "optimizedScroll");
})();

window.addEventListener("optimizedScroll", function() {
  console.log("Resource conscious scroll callback!");
});

上边代码中,throttle函数用于调整事件触发频率,requestAnimationFrame方法保险每回页面重绘(每秒伍19次),只会接触叁次scroll事件的监听函数。改用set提姆eout方法,能够放置更加大的大运输间隔离。

(function() {
  window.addEventListener("scroll", scrollThrottler, false);

  var scrollTimeout;
  function scrollThrottler() {
    if ( !scrollTimeout ) {
      scrollTimeout = setTimeout(function() {
        scrollTimeout = null;
        actualScrollHandler();
      }, 66);
    }
  }

  function actualScrollHandler() {
    // ...
  }
}());

地点代码中,set提姆eout钦定scroll事件的监听函数,每66皮秒触发一遍(每秒十八回)。

(2)resize事件

resize事件在改换浏览器窗口大小时触发,发生在window、body、frameset对象方面。

var resizeMethod = function(){
  if (document.body.clientWidth < 768) {
    console.log('移动设备');
  }
};

window.addEventListener("resize", resizeMethod, true);

该事件也会接连地质大学方触及,所以最相同下边的scroll事件相通,通过throttle函数调整事件触发频率。

hashchange事件,popstate事件

以下事件与文书档案的U中华VL变化有关。

(1)hashchange事件

hashchange事件在URL的hash部分(即#号后边的一对,包涵#号)发生变化时接触。假诺老式浏览器不支持该属性,能够透过准时检查location.hash属性,模拟该事件,上面正是代码。

(function(window) {
  if ( "onhashchange" in window.document.body ) { return; }

  var location = window.location;
  var oldURL = location.href;
  var oldHash = location.hash;

  // 每隔100毫秒检查一下URL的hash
  setInterval(function() {
    var newURL = location.href;
    var newHash = location.hash;

    if ( newHash != oldHash && typeof window.onhashchange === "function" ) {
      window.onhashchange({
        type: "hashchange",
        oldURL: oldURL,
        newURL: newURL
      });

      oldURL = newURL;
      oldHash = newHash;
    }
  }, 100);

})(window);

hashchange事件对象除了世襲Event对象,还会有oldUHavalL属性和newUHighlanderL属性,分别代表变化前后的U帕杰罗L。

(2)popstate事件

popstate事件在浏览器的history对象的此时此刻记录发生显式切换时接触。注意,调用history.pushState(卡塔尔国或history.replaceState(卡塔尔国,并不会触发popstate事件。该事件只在客商在history记录之间显式切换时接触,举个例辰龙标点击“后退/前行”开关,可能在剧本中调用history.back(卡塔尔国、history.forward(卡塔尔(قطر‎、history.go(State of Qatar时接触。

该事件指标有四个state属性,保存history.pushState方法和history.replaceState方法为最近记录增多的state对象。

window.onpopstate = function(event) {
  console.log("state: " + event.state);
};
history.pushState({page: 1}, "title 1", "?page=1");
history.pushState({page: 2}, "title 2", "?page=2");
history.replaceState({page: 3}, "title 3", "?page=3");
history.back(); // state: {"page":1}
history.back(); // state: null
history.go(2);  // state: {"page":3}

地点代码中,pushState方法向history增多了两条记下,然后replaceState方法替换掉当前记下。因而,三番一次若干遍back方法,会让近年来条约退回到原本网站,它从不附带state对象,所以事件的state属性为null,然后前行两条记下,又赶回replaceState方法加多的笔录。

浏览器对于页面第一回加载,是否触发popstate事件,管理不相像,Firefox不触发该事件。

cut事件,copy事件,paste事件

以下八个事件归于文本操作触发的事件。

  • cut事件:在将当选的内容从文档中移除,参加剪贴板后触发。

  • copy事件:在当选的内容参与剪贴板后触发。

  • paste事件:在剪贴板内容被粘贴到文书档案后触发。

那多少个事件都有三个clipboardData只读属性。该属性存放剪贴的数量,是叁个DataTransfer对象,具体的API接口和操作方法,请参见《触摸事件》的DataTransfer对象章节。

症结事件

要点事件产生在Element节点和document对象方面,与收获或失去核心相关。它至关心重视要包涵以下八个事件。

  • focus事件:Element节点获得大旨后触发,该事件不会冒泡。

  • blur事件:Element节点失去主旨后触发,该事件不会冒泡。

  • focusin事件:Element节点就要获得核心时接触,发生在focus事件早先。该事件会冒泡。Firefox不扶持该事件。

  • focusout事件:Element节点将在失去大旨时接触,产生在blur事件早前。该事件会冒泡。Firefox不援助该事件。

那多个事件的风浪指标,带有target属性(重返事件的靶子节点)和relatedTarget属性(再次回到一个Element节点)。对于focusin事件,relatedTarget属性表示失去主题的节点;对于focusout事件,表示将在经受主题的节点;对于focus和blur事件,该属性再次来到null。

鉴于focus和blur事件不会冒泡,只可以在捕获阶段触发,所以add伊夫ntListener方法的第八个参数要求设为true。

form.addEventListener("focus", function( event ) {
  event.target.style.background = "pink";
}, true);
form.addEventListener("blur", function( event ) {
  event.target.style.background = "";
}, true);

上面代码设置表单的公文输入框,在经受主旨时设置背景象,在失去宗旨时去除背景观。

浏览器提供四个Focus伊芙nt构造函数,能够用它生成标准事件的实例。

var focusEvent = new FocusEvent(typeArg, focusEventInit);

地点代码中,FocusEvent布局函数的第叁个参数为事件类型,第1个参数是可选的配置对象,用来配置FocusEvent对象。

自定义事件和事件模拟

除此而外浏览器预约义的那多少个事件,顾客还能自定义事件,然后手动触发。

// 新建事件实例
var event = new Event('build');

// 添加监听函数
elem.addEventListener('build', function (e) { ... }, false);

// 触发事件
elem.dispatchEvent(event);

上边代码触发了自定义事件,该事件会层层升高冒泡。在冒泡进度中,如若有一个要素定义了该事件的监听函数,该监听函数就能触发。

是因为IE不援救那几个API,假使在IE中自定义事件,要求动用后文的“老式方法”。

CustomEvent()

伊夫nt布局函数只可以钦命事件名,不可能在事变上绑定数据。要是必要在触及事件的同一时候,传入钦赐的数额,供给选取CustomEvent布局函数生成自定义的事件目的。

var event = new CustomEvent('build', { 'detail': 'hello' });
function eventHandler(e) {
  console.log(e.detail);
}

上面代码中,Custom伊夫nt构造函数的第三个参数是事件名称,第二个参数是叁个对象,该对象的detail属性会绑定在事变指标之上。

下边是另八个例子。

var myEvent = new CustomEvent("myevent", {
  detail: {
    foo: "bar"
  },
  bubbles: true,
  cancelable: false
});

el.addEventListener('myevent', function(event) {
  console.log('Hello ' + event.detail.foo);
});

el.dispatchEvent(myEvent);

IE不帮衬这么些法子,能够用上边的垫子函数模拟。

(function () {
  function CustomEvent ( event, params ) {
    params = params || { bubbles: false, cancelable: false, detail: undefined };
    var evt = document.createEvent( 'CustomEvent' );
    evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
    return evt;
   }

  CustomEvent.prototype = window.Event.prototype;

  window.CustomEvent = CustomEvent;
})();

事件的模仿

不经常,须要在剧本中模仿触发某体系型的风浪,那时候就不得不接收这种事件的布局函数。

上面是三个因而MouseEvent构造函数,模拟触发click鼠标事件的事例。

function simulateClick() {
  var event = new MouseEvent('click', {
    'bubbles': true,
    'cancelable': true
  });
  var cb = document.getElementById('checkbox');
  cb.dispatchEvent(event);
}

自定义事件的老一套写法

老式浏览器不必然帮忙各系列型事件的布局函数。由此,一时为了协作,会用到部分非标准的点子。那些办法以后会被慢慢淘汰,但是当前浏览器还广大扶植。除非是为着同盟老式浏览器,尽量不要选拔。

(1)document.createEvent()

document.createEvent方法用来新建钦命项目标事件。它所生成的Event实例,能够流传dispatch伊夫nt方法。

// 新建Event实例
var event = document.createEvent('Event');

// 事件的初始化
event.initEvent('build', true, true);

// 加上监听函数
document.addEventListener('build', doSomething, false);

// 触发事件
document.dispatchEvent(event);

createEvent方法选取叁个字符串作为参数,可能的值参见下表“数据类型”一栏。使用了某一种“事件类型”,就必需利用相应的平地风波伊始化方法。

事件类型 事件初始化方法
UIEvents event.initUIEvent
MouseEvents event.initMouseEvent
MutationEvents event.initMutationEvent
HTMLEvents event.initEvent
Event event.initEvent
CustomEvent event.initCustomEvent
KeyboardEvent event.initKeyEvent

(2)event.initEvent()

事件指标的initEvent方法,用来发轫化事件目的,还是能向事件目的加多属性。该办法的参数必得是贰个运用Document.createEvent()更换的Event实例,何况必需在dispatch伊夫nt方法以前调用。

var event = document.createEvent('Event');
event.initEvent('my-custom-event', true, true, {foo:'bar'});
someElement.dispatchEvent(event);

init伊夫nt方法可以承当七个参数。

  • type:事件名称,格式为字符串。
  • bubbles:事件是或不是应当冒泡,格式为布尔值。能够行使event.bubbles属性读取它的值。
  • cancelable:事件是或不是能被撤销,格式为布尔值。能够利用event.cancelable属性读取它的值。
  • option:为事件指标内定额外的本性。

事件模拟的不符合时机写法

事件模拟的非标准做法是,对document.create伊夫nt方法生成的轩然大波目的,使用相应的事件早先化方法开张开始化。比如,click事件目的归属MouseEvent对象,也归于UIEvent对象,因而要用initMouseEvent方法或initUI伊夫nt方法开展起头化。

(1)event.initMouseEvent()

initMouseEvent方法用来开始化Document.createEvent方法新建的鼠标事件。该方法必需在事变新建(document.create伊夫nt方法)之后、触发(dispatch伊夫nt方法)从前调用。

initMouse伊芙nt方法有非常短的参数。

event.initMouseEvent(type, canBubble, cancelable, view,
  detail, screenX, screenY, clientX, clientY,
  ctrlKey, altKey, shiftKey, metaKey,
  button, relatedTarget
);

地点这个参数的意义,参见MouseEvent布局函数的片段。

仿照并触发click事件的写法如下。

var simulateDivClick = document.createEvent('MouseEvents');

simulateDivClick.initMouseEvent('click',true,true,
  document.defaultView,0,0,0,0,0,false,
  false,false,0,null,null
);

divElement.dispatchEvent(simulateDivClick);

(2)UIEvent.initUIEvent()

UIEvent.initUIEvent()用来早先化二个UI事件。该措施必得在事件新建(document.createEvent方法)之后、触发(dispatch伊夫nt方法)早前调用。

event.initUIEvent(type, canBubble, cancelable, view, detail)

该方法的参数含义,能够敬重MouseEvent布局函数的有些。个中,detail参数是二个数值,含义与事件类型有关,对于鼠标事件,这一个值表示鼠标开关在某些地方按下的次数。

var e = document.createEvent("UIEvent");
e.initUIEvent("click", true, true, window, 1);

<h2 id=”5.6″>CSS操作</h2>

CSS与JavaScript是五个具有明显分工的圈子,后面一个担当页面包车型大巴视觉效果,前者肩负与客户的一言一行相互影响。可是,它们毕竟同属网页开采的前端,由此不可幸免有着交叉和互般合营。本节介绍假诺通过JavaScript操作CSS。

HTML元素的style属性

操作Element节点的CSS样式,最简易的措施之一就是接收节点目的的getAttribute方法、setAttribute方法和removeAttribute办法,读写或删除HTML成分的style属性。

div.setAttribute('style',
  'background-color:red;' + 'border:1px solid black;'
);

那四个法子的详实用法,详见《Node节点》一节。

Element节点的style属性

骨干用法

Element节点自身还提供style质量,用来操作CSS样式。style属性指向一个对象,用来读写页面成分的行内CSS样式。

var divStyle = document.querySelector('div').style;

divStyle.backgroundColor = 'red';
divStyle.border = '1px solid black';
divStyle.width = '100px';
divStyle.height = '100px';
divStyle.fontSize = '10em';

divStyle.backgroundColor // red
divStyle.border // 1px solid black
divStyle.height // 100px
divStyle.width // 100px

从地方代码能够观望,style对象的性质与CSS准绳名一一对应,可是急需改写。具体法规是将横杠从CSS属性名中去除,然后将横杠后的率先个假名大写,例如background-color写成backgroundColor。假若CSS属性名是JavaScript保留字,则法则名早前供给丰硕字符串“css”,例如float写成cssFloat

注意,style对象的属性值都是字符串,况且包涵单位。所以,divStyle.width无法设置为100,而要设置为100px

cssText属性

style对象的cssText能够用来读写或删除全体style属性。

var divStyle = document.querySelector('div').style;

divStyle.cssText = 'background-color: red;'
  + 'border: 1px solid black;'
  + 'height: 100px;'
  + 'width: 100px;';

注意,cssText的属性值不用改写CSS属性名。

CSS模块的侦测

CSS的口径发展太快,新的模块不可胜道。分歧浏览器的不如版本,对CSS模块的支撑情况都不相符。有时候,需求领悟当前浏览器是还是不是协助有个别模块,那就称为“CSS模块的侦测”。

三个相比较高高挂起适用的艺术是,判定有些DOM成分的style对象的某部属性值是或不是为字符串。

typeof element.style.animationName === 'string';
typeof element.style.transform === 'string';

一经该CSS属性确实存在,会回到叁个字符串。固然该属性实际上并未安装,也会重回八个空字符串。假如该属性不设有,则会回来undefined

document.body.style['maxWidth'] // ""
document.body.style['maximumWidth'] // undefined

亟需注意的是,不管CSS属性名带不带连词线,style目的都博览会示该属性存在。

document.body.style['backgroundColor'] // ""
document.body.style['background-color'] // ""

不无浏览器都能用那几个办法,可是利用的时候,要求把不一样浏览器的CSS法规前缀也假造进来。

var content = document.getElementById("content");
typeof content.style['webkitAnimation'] === 'string'

这种侦测方法能够写成二个函数。

function isPropertySupported(property){
  if (property in document.body.style) return true;
  var prefixes = ['Moz', 'Webkit', 'O', 'ms', 'Khtml'];
  var prefProperty = property.charAt(0).toUpperCase() + property.substr(1);

  for(var i = 0; i < prefixes.length; i++){
    if((prefixes[i] + prefProperty) in document.body.style) return true;
  }

  return false;
}

isPropertySupported('background-clip')
// true

除此以外,部分浏览器(Firefox 22+, Chrome 28+, Opera
12.1+)这段日子布置了supports
API,可以再次来到四个布尔值,表示是还是不是帮衬某条CSS准则。可是,那些API还尚无成为行业内部。

CSS.supports('transform-origin', '5px');
CSS.supports('(display: table-cell) and (display: list-item)');

setProperty(),getPropertyValue(),removeProperty()

style指标的以下多少个主意,用来读写行内CSS法则。

  • setProperty(propertyName,value):设置有些CSS属性。
  • getPropertyValue(propertyName):读取有些CSS属性。
  • removeProperty(propertyName):删除有些CSS属性。

这四个主意的率先个参数,都是CSS属性名,且毫无改写连词线。

var divStyle = document.querySelector('div').style;

divStyle.setProperty('background-color','red');
divStyle.getPropertyValue('background-color');
divStyle.removeProperty('background-color');

CSS伪元素

CSS伪成分是透过CSS向DOM增加的成分,首要方式是由此:before:after接收器生成伪成分,然后用content属性钦定伪成分的剧情。

以如下HTML代码为例。

<div id="test">Test content</div>

CSS加多伪成分的写法如下。

#test:before {
  content: 'Before ';
  color: #FF0;
}

DOM节点的style目的不可能读写伪成分的体制,那时候将要动用window对象的getComputedStyle主意(详见上边介绍)。JavaScript获取伪成分,可以采纳下边包车型地铁章程。

var test = document.querySelector('#test');

var result = window.getComputedStyle(test, ':before').content;
var color = window.getComputedStyle(test, ':before').color;

别的,也得以采取window.getComputedStyle对象的getPropertyValue方法,获取伪成分的本性。

var result = window.getComputedStyle(test, ':before')
  .getPropertyValue('content');
var color = window.getComputedStyle(test, ':before')
  .getPropertyValue('color');

StyleSheet对象

获取样式表

StyleSheet对象表示网页的一张样式表,它回顾link节点加载的样式表和style节点内嵌的样式表。

document对象的styleSheets属性,能够回来当前页面包车型地铁具有StyleSheet对象(即具备样式表)。它是三个好像数组的指标。

var sheets = document.styleSheets;
var sheet = document.styleSheets[0];

别的,link节点和style节点的sheet属性,也得以获得StyleSheet对象。

// HTML代码为
// <link id="linkElement" href="http://path/to/stylesheet">
// <style id="styleElement">
//   body{font-size: 1.2 rem;}
// </style>

// 等同于document.styleSheets[0]
document.querySelector('#linkElement').sheet

// 等同于document.styleSheets[1]
document.querySelector('#styleElement').sheet

属性

StyleSheet对象有以下属性。

(1)media属性

media属性表示那一个样式表是用于荧屏(screen),依然用来打字与印刷(print),或二者都适用(all)。该属性只读,暗中同意值是screen。

document.styleSheets[0].media.mediaText
// "all"

(2)disabled属性

disabled天性用于打开或关闭一张样式表。

document.querySelector('#linkElement').disabled = true;
// 或者
document.querySelector('#linkElement').disabled = 'disabled';

假诺样式表设置了disabled质量,那张样式表就将失效。

注意,disabled特性只可以在JavaScript中安装,不可能在HTML语句中装置。

(3)href属性

href属性是只读属性,重返StyleSheet对象连接的样式表地址。对于内嵌的style节点,该属性等于null。

document.styleSheets[0].href

(4)title属性

title属性再次回到StyleSheet对象的title值。

(5)type属性

type属性重回StyleSheet对象的type值,平日是text/css。

document.styleSheets[0].type  // "text/css"

(6)parentStyleSheet属性

CSS的@import命令允许在样式表中加载其余样式表。parentStyleSheet属性重返包涵了当下样式表的那张样式表。假设当前样式表是顶层样式表,则该属性重回null。

if (stylesheet.parentStyleSheet) {
    sheet = stylesheet.parentStyleSheet;
} else {
    sheet = stylesheet;
}

(7)ownerNode属性

ownerNode属性重返StyleSheet对象所在的DOM节点,平日是<link>或<style>。对于这个由别的样式表援引的样式表,该属性为null。

// HTML代码为
// <link rel="StyleSheet" href="example.css" type="text/css" />

document.styleSheets[0].ownerNode // [object HTMLLinkElement]

(8)cssRules属性

cssRules属性指向二个好像数组的靶子,里面每二个分子正是当下样式表的一条CSS准绳。使用该准绳的cssText属性,能够获得CSS准则对应的字符串。

var sheet = document.querySelector('#styleElement').sheet;

sheet.cssRules[0].cssText
// "body { background-color: red; margin: 20px; }"

sheet.cssRules[1].cssText
// "p { line-height: 1.4em; color: blue; }"

每条CSS法则还会有贰个style属性,指向二个指标,用来读写实际的CSS命令。

styleSheet.cssRules[0].style.color = 'red';
styleSheet.cssRules[1].style.color = 'purple';

insertRule(),deleteRule()

insertRule格局用于在当前样式表的cssRules指标插入CSS准绳,deleteRule措施用于删除cssRules对象的CSS规则。

var sheet = document.querySelector('#styleElement').sheet;
sheet.insertRule('#block { color:white }', 0);
sheet.insertRule('p { color:red }',1);
sheet.deleteRule(1);

insertRule方法的首先个参数是代表CSS准绳的字符串,第1个参数是该法规在cssRules指标的插入地方。deleteRule形式的参数是该条法规在cssRules目的中之处。

增多样式表

增添样式表有二种方法。一种是增添一张内置样式表,即在文档中增添贰个<style>节点。

var style = document.createElement('style');

style.setAttribute('media', 'screen');
// 或者
style.setAttribute("media", "@media only screen and (max-width : 1024px)");

style.innerHTML = 'body{color:red}';
// 或者
sheet.insertRule("header { float: left; opacity: 0.8; }", 1);

document.head.appendChild(style);

另一种是丰富表面样式表,即在文书档案中加多三个link节点,然后将href属性指向外界样式表的UWranglerL。

var linkElm = document.createElement('link');
linkElm.setAttribute('rel', 'stylesheet');
linkElm.setAttribute('type', 'text/css');
linkElm.setAttribute('href', 'reset-min.css');

document.head.appendChild(linkElm);

CSS规则

一条CSS准则包涵四个部分:CSS选择器和体制证明。上面正是一条优越的CSS准绳。

.myClass {
  background-color: yellow;
}

CSSRule接口

CSS准则铺排了CSSRule接口,它回顾了以下属性。

(1)cssText

cssText属性重回当前准绳的文书。

// CSS代码为
// body { background-color: darkblue; }

var stylesheet = document.styleSheets[0];
stylesheet.cssRules[0].cssText
// body { background-color: darkblue; }

(2)parentStyleSheet

parentStyleSheet属性重临定义当前准绳的样式表对象。

(3)parentRule

parentRule再次回到满含当前法规的这条CSS准绳。最规范的意况,正是眼下准则包括在一个@media代码块之中。假若当前法则是顶层法则,则该属性再次来到null。

(4)type

type属性再次来到有一个整数值,表示目前准绳的门类。

最广大的品种有以下几种。

  • 1:样式准绳,安排了CSSStyleRule接口
  • 3:输入法则,安顿了CSSImportRule接口
  • 4:Media规则,部署了CSSMediaRule接口
  • 5:字体法则,陈设了CSSFontFaceRule接口

CSSStyleRule接口

设若一条CSS法则是司空见惯的体制法规,那么除了CSSRule接口,它还安顿了CSSStyleRule接口。

CSSRule接口有以下多少个特性。

(1)selectorText属性

selectorText属性重临当前准则的采用器。

var stylesheet = document.styleSheets[0];
stylesheet.cssRules[0].selectorText // ".myClass"

(2)style属性

style属性重返八个对象,代表当前法则的体裁证明,也便是选择器后边的大括号里面的局地。该对象布署了CSSStyleDeclaration接口,使用它的cssText属性,能够回来全体样式评释,格式为字符串。

document.styleSheets[0].cssRules[0].style.cssText
// "background-color: gray;font-size: 120%;"

CSSMediaRule接口

倘使一条CSS法规是@media代码块,那么它除了CSSRule接口,还配置了CSSMediaRule接口。

该接口主要提供叁个media属性,可以回来@media代码块的media准则。

CSSStyleDeclaration对象

每一条CSS准则的体裁表明部分(大括号内部的有个别),都以三个CSSStyleDeclaration对象,首要总结三种景况。

  • HTML成分的行内样式(<elem style=”…”>)

  • CSSStyleRule接口的style属性

  • window.getComputedStyle(卡塔尔国的回来结果

每一条CSS属性,都以CSSStyleDeclaration对象的性质。不过,连词号供给编制程序骆驼拼写法。

var styleObj = document.styleSheets[0].cssRules[1].style;
styleObj.color // "red";
styleObj.fontSize // "100%"

除了那么些之外CSS属性以外,CSSStyleDeclaration对象还包蕴以下属性。

  • cssText:当前准绳的具有样式证明文本。该属性可读写,就能够用来安装当前准则。

  • length:当前法规包涵多少条注明。

  • parentRule:包涵当前准则的那条准绳,同CSSRule接口的parentRule属性。

CSSStyleDeclaration对象满含以下办法。

(1)getPropertyPriority()

getPropertyPriority方法重返内定注解的优先级,假若有的话,便是“important”,不然正是空字符串。

var styleObj = document.styleSheets[0].cssRules[1].style;
styleObj.getPropertyPriority('color') // ""

(2)getPropertyValue()

getPropertyValue方法重回钦点证明的值。

// CSS代码为
// color:red;

var styleObj = document.styleSheets[0].cssRules[1].style;
styleObj.getPropertyValue('color') // "red"

(3)item()

item方法重返钦命地方的属性名。

var styleObj = document.styleSheets[0].cssRules[1].style;
styleObj.item(0) // "color"
// 或者
styleObj[0] // "color"

(4)removeProperty()

removeProperty方法用于删除一条CSS属性,再次回到被去除的值。

// CSS代码为
// color:red;

var styleObj = document.styleSheets[0].cssRules[1].style;
styleObj.removeProperty('color') // "red"

(5)setProperty()

setProperty方法用于安装钦赐的CSS属性,没有重临值。

var styleObj = document.styleSheets[0].cssRules[1].style;
styleObj.setProperty('color', 'green', 'important');

下边是遍历一条CSS准则全体属性的例证。

var styleObj = document.styleSheets[0].cssRules[0].style;
for (var i = styleObj.length - 1; i >= 0; i--) {
   var nameString = styleObj[i];
   styleObj.removeProperty(nameString);
}

地点删除了一条CSS法则的兼具属性,更轻巧的不二等秘书诀是安装cssText属性为空字符串。

styleObj.cssText = '';

window.getComputedStyle()

getComputedStyle艺术选取三个DOM节点目的作为参数,再次回到三个包涵该节点最后样式音信的对象。所谓“最后样式消息”,指的是种种CSS法规叠合后的结果。

var div = document.querySelector('div');
window.getComputedStyle(div).backgroundColor

getComputedStyle方法还足以承当第一个参数,表示钦命节点的伪成分。

var result = window.getComputedStyle(div, ':before');

getComputedStyle方法再次回到的是三个CSSStyleDeclaration对象。不过那时,这么些指标是只读的,约等于一定要用来读取样式音信,不能够用来安装。若是想设置样式,应该选拔Element节点的style属性。

var elem = document.getElementById("elem-container");
var hValue = window.getComputedStyle(elem,null).getPropertyValue("height");

window.matchMedia()

基本用法

window.matchMedia方式用来检查CSS的mediaQuery言辞。各个浏览器的风靡版本(包蕴IE
10+)都支持该方法,对于不援助该办法的过时浏览器,能够应用第三方函数库matchMedia.js。

CSS的mediaQuery说话有一点点像if话语,只要出示媒介(包罗浏览器和显示屏等)满意mediaQuery说话设定的尺码,就能够试行区块内部的言辞。下边是mediaQuery言语的二个例证。

@media all and (max-width: 700px) {
  body {
    background: #FF0;
  }
}

地方的CSS代码表示,该区块对具有媒介(media)有效,且视口的最大开间不得超越700像素。假使条件知足,则body要素的背景设为#FF0。

亟需静心的是,mediaQuery选拔二种宽度/中度的心路,一种是上例的“视口”的上涨的幅度/中度,还大概有一种是“设备”的上升的幅度/高度,上边正是二个例子。

@media all and (max-device-width: 700px) {
  body {
    background: #FF0;
  }
}

视口的宽窄/中度(width/height)使用documentElement.clientWidth/clientHeight来衡量,单位是CSS像素;设备的大幅/中度(device-width/device-height)使用screen.width/height来衡量,单位是器材硬件的像素。

window.matchMedia措施接纳多个mediaQuery言辞的字符串作为参数,再次来到二个MediaQueryList对象。该对象有以下八个属性。

  • media:再次回到所查询的mediaQuery语句字符串。
  • matches:重回一个布尔值,表示这段时间条件是或不是同盟查询语句。

var result = window.matchMedia('(min-width: 600px)');
result.media // (min-width: 600px)
result.matches // true

上边是别的一个例子,依据mediaQuery是还是不是同盟当前条件,实施不一致的JavaScript代码。

var result = window.matchMedia('(max-width: 700px)');

if (result.matches) {
  console.log('页面宽度小于等于700px');
} else {
  console.log('页面宽度大于700px');
}

下边包车型客车例子依据mediaQuery是还是不是相配当前条件,加载相应的CSS样式表。

var result = window.matchMedia("(max-width: 700px)");

if (result.matches){
  var linkElm = document.createElement('link');
  linkElm.setAttribute('rel', 'stylesheet');
  linkElm.setAttribute('type', 'text/css');
  linkElm.setAttribute('href', 'small.css');

  document.head.appendChild(linkElm);
}

注意,如果window.matchMedia无法深入分析mediaQuery参数,再次回到的三回九转false,实际不是报错。

window.matchMedia('bad string').matches
// false

监听事件

window.matchMedia方法回来的MediaQueryList对象有四个措施,用来监听事件:addListener方法和removeListener方法。若是mediaQuery查询结果产生变化,就调用钦命的回调函数。

var mql = window.matchMedia("(max-width: 700px)");

// 指定回调函数
mql.addListener(mqCallback);

// 撤销回调函数
mql.removeListener(mqCallback);

function mqCallback(mql) {
  if (mql.matches) {
    // 宽度小于等于700像素
  } else {
    // 宽度大于700像素
  }
}

地点代码中,回调函数的参数是MediaQueryList对象。回调函数的调用大概存在二种情况。一种是展现上升的幅度从700像素以上变为以下,另一种是从700像素以下变为以上,所以在回调函数内部要看清一下当下的显示屏宽度。

CSS事件

transitionEnd事件

CSS的接入效果(transition)截至后,触发transitionEnd事件。

el.addEventListener('transitionend', onTransitionEnd, false);

function onTransitionEnd() {
  console.log('Transition end');
}

transitionEnd的事件目的具有以下属性。

  • propertyName:发生transition效果的CSS属性名。
  • elapsedTimetransition职能不断的秒数,不含transition-delay的时间。
  • pseudoElement:如果transition效果爆发在伪成分,会回去该伪成分的名目,以“::”初步。假若不发出在伪成分上,则赶回一个空字符串。

事实上行使transitionend事件时,大概须求加上浏览器前缀。

el.addEventListener('webkitTransitionEnd', function () {
    el.style.transition = 'none';
});

animationstart事件,animationend事件,animationiteration事件

CSS动漫有以下三个事件。

  • animationstart事件:动漫开首时接触。

  • animationend事件:动漫截至时接触。

  • animationiteration事件:初步新一轮动漫循环时接触。借使animation-iteration-count属性等于1,该事件不接触,即只播放一轮的CSS动漫,不会触发animationiteration事件。

div.addEventListener('animationiteration', function() {
  console.log('完成一次动画');
});

那多个事件的风浪目的,都有animationName属性(重临爆发过渡效果的CSS属性名)和elapsedTime属性(动漫已经运营的秒数)。对于animationstart事件,elapsedTime属性等于0,除非animation-delay属性等于负值。

var el = document.getElementById("animation");

el.addEventListener("animationstart", listener, false);
el.addEventListener("animationend", listener, false);
el.addEventListener("animationiteration", listener, false);

function listener(e) {
  var li = document.createElement("li");
  switch(e.type) {
    case "animationstart":
      li.innerHTML = "Started: elapsed time is " + e.elapsedTime;
      break;
    case "animationend":
      li.innerHTML = "Ended: elapsed time is " + e.elapsedTime;
      break;
    case "animationiteration":
      li.innerHTML = "New loop started at time " + e.elapsedTime;
      break;
  }
  document.getElementById("output").appendChild(li);
}

地方代码的运营结果是上面的标准。

Started: elapsed time is 0
New loop started at time 3.01200008392334
New loop started at time 6.00600004196167
Ended: elapsed time is 9.234000205993652

animation-play-state属性能够调节动漫的事态(暂停/播放),该属性必要增进浏览器前缀。

element.style.webkitAnimationPlayState = "paused";
element.style.webkitAnimationPlayState = "running";

<h2 id=”5.7″>Mutation Observer</h2>

概述

Mutation
Observer(变动观望器)是监视DOM变动的接口。DOM产生其余变动,Mutation
Observer会得到文告。

概念上,它很接近事件。能够领略为,当DOM发生改动,会触发Mutation
Observer事件。可是,它与事件有三个真相分裂:事件是同步触发,也正是说,当DOM发生更动,立时会触发相应的平地风波;Mutation
Observer则是异步触发,DOM发生改换今后,并不会及时触发,而是要等到当前具有DOM操作都得了后才触发。

这样设计是为着敷衍DOM变动频仍的特色。比释迦牟尼讲,假设在文书档案中三番三遍插入1000个段落(p元素),就能三番若干回触发1000个插入事件,实行各样事件的回调函数,那很恐怕诱致浏览器的卡顿;而Mutation
Observer完全两样,只在1000个段子都插入截至后才会接触,何况只触发一遍。

Mutation Observer有以下特征:

  • 它等待全部脚本任务成功后,才会运转,即采用异步格局。

  • 它把DOM变动记录封装成叁个数组举行拍卖,实际不是一条条地分别处理DOM变动。

  • 它不仅能考查发生在DOM的享有项目更改,也足以洞察某一类变动。

近日,Firefox(14+)、
Chrome(26+卡塔尔(قطر‎、Opera(15+)、IE(11+)和Safari(6.1+)扶植那个API。Safari
6.0和Chrome
18-25施用这些API的时候,需求加上Web基特前缀(WebKitMutationObserver)。能够动用下边包车型客车表达式,检查当前浏览器是不是扶植这几个API。

var MutationObserver = window.MutationObserver
  || window.WebKitMutationObserver
  || window.MozMutationObserver;

var observeMutationSupport = !!MutationObserver;

MutationObserver构造函数

率先,使用MutationObserver布局函数,新建一个观看器实例,同一时候内定这几个实例的回调函数。

var observer = new MutationObserver(callback);

观察器的回调函数会在每一遍DOM发生变动后调用。它担当多个参数,第贰个是改造数组(详见后文),第一个是阅览器实例。

Mutation Observer实例的办法

observe()

observe方法钦点所要观望的DOM节点,以至所要寓目标特定变动。

var article = document.querySelector('article');

var  options = {
  'childList': true,
  'attributes':true
} ;

observer.observe(article, options);

上边代码中,observe方法选拔八个参数,第一个是所要观望的DOM元素是article,第四个是所要观望的改动类型(子节点变动和总体性别变化动)。

观看器所能观望的DOM变动类型(即上边代码的options对象),有以下三种:

  • childList:子节点的改进。
  • attributes:属性的更换。
  • characterData:节点内容或节点文本的改革。
  • subtree:全体后代节点的改观。

想要阅览哪一类更换类型,就在option对象中钦点它的值为true。供给注意的是,不可能独立阅览subtree变动,必需同临时候内定childList、attributes和characterData中的一种或两种。

除去更改类型,options对象还是可以够设定以下属性:

  • attributeOldValue:类型为布尔值,表示观看attributes变动时,是或不是供给记录变动前的属性值。

  • characterDataOldValue:类型为布尔值,表示阅览characterData变动时,是还是不是需求记录变动前的值。

  • attributeFilter:类型为数组,表示供给重点的一定属性(举例[‘class’,’src’])。

对一个节点增加观望器,就疑似增加add伊夫ntListener方法同样。多次增多同一个观察器是不行的,回调函数依旧只会触发三回。不过,假设钦命不相同的options对象,就能够被看作五个不等的观望器。

上边的例子观望新添的子节点。

var insertedNodes = [];
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    for (var i = 0; i < mutation.addedNodes.length; i++)
      insertedNodes.push(mutation.addedNodes[i]);
  })
});
observer.observe(document, { childList: true });
console.log(insertedNodes);

disconnect(),takeRecords()

disconnect方法用来终止观看。再产生相应改造,就不再调用回调函数。

observer.disconnect();

takeRecords方法用来撤除变动记录,即不再管理未处理的更改。该办法再次回到变动记录的数组。

observer.takeRecords();

MutationRecord对象

DOM每回发生变化,就能够生成一条变动记录。那些纠正记录对应贰个MutationRecord对象,该目标包括了与改观相关的有所新闻。Mutation
Observer管理的是一个个MutationRecord对象所结合的数组。

MutationRecord对象满含了DOM的连带音讯,犹如下属性:

  • type:寓目的退换类型(attribute、characterData或然childList)。
  • target:发生变动的DOM节点。
  • addedNodes:新增的DOM节点。
  • removedNodes:删除的DOM节点。
  • previousSibling:前三个同级节点,若无则赶回null。
  • nextSibling:下一个同级节点,如果未有则赶回null。
  • attributeName:发生转移的属性。要是设置了attributeFilter,则只回去预先钦点的质量。
  • oldValue:变动前的值。那本性情只对attribute和characterData变动有效,若是发生childList变动,则赶回null。

运用示范

子成分的转移

下边包车型大巴事例表达什么读取变动记录。

var callback = function(records){
  records.map(function(record){
    console.log('Mutation type: ' + record.type);
    console.log('Mutation target: ' + record.target);
  });
};

var mo = new MutationObserver(callback);

var option = {
  'childList': true,
  'subtree': true
};

mo.observe(document.body, option);

地点代码的观看器,寓目body的有所下级节点(childList表示观看子节点,subtree代表观看后代节点)的转移。回调函数会在调整台展现全体制纠正变的花色和目的节点。

属性的更改

下面包车型地铁例子表达什么追踪属性的校正。

var callback = function(records){
  records.map(function(record){
    console.log('Previous attribute value: ' + record.oldValue);
  });
};

var mo = new MutationObserver(callback);

var element = document.getElementById('#my_element');

var options = {
  'attributes': true,
  'attributeOldValue': true
}

mo.observe(element, options);

地方代码先设定追踪属性别变化动(’attributes’:
true),然后设定记录变动前的值。实际产生退换时,会将转移前的值突显在调整台。

取代DOMContentLoaded事件

网页加载的时候,DOM节点的生成会产生变动记录,因而借使观看DOM的改良,就能够在第偶然间触发相关事件,因而也就一直不必要采纳DOMContentLoaded事件。

var observer = new MutationObserver(callback);
observer.observe(document.documentElement, {
  childList: true,
  subtree: true
});

地点代码中,监听document.documentElement(即HTML节点)的子节点的改观,subtree属性钦定监听还满含后代节点。因而,放肆二个网页元素一旦生成,就会及时被监听到。

下边的代码,使用MutationObserver对象封装三个监听DOM生成的函数。

(function(win){
  'use strict';

  var listeners = [];
  var doc = win.document;
  var MutationObserver = win.MutationObserver || win.WebKitMutationObserver;
  var observer;

  function ready(selector, fn){
    // 储存选择器和回调函数
    listeners.push({
      selector: selector,
      fn: fn
    });
    if(!observer){
      // 监听document变化
      observer = new MutationObserver(check);
      observer.observe(doc.documentElement, {
        childList: true,
        subtree: true
      });
    }
    // 检查该节点是否已经在DOM中
    check();
  }

  function check(){
  // 检查是否匹配已储存的节点
    for(var i = 0; i < listeners.length; i++){
      var listener = listeners[i];
      // 检查指定节点是否有匹配
      var elements = doc.querySelectorAll(listener.selector);
      for(var j = 0; j < elements.length; j++){
        var element = elements[j];
        // 确保回调函数只会对该元素调用一次
        if(!element.ready){
          element.ready = true;
          // 对该节点调用回调函数
          listener.fn.call(element, element);
        }
      }
    }
  }

  // 对外暴露ready
  win.ready = ready;

})(this);

ready('.foo', function(element){
  // ...
});

发表评论

电子邮件地址不会被公开。 必填项已用*标注