响应用户操作和事件

事件就是操作检测与脚本执行的组合,或者基于检测到的操作类型在某个对象上调用事件侦听器(事件处理程序)。

事件的类型

事件可以分为几种类型:对象事件,鼠标事件,键盘事件(只适用于document对象),表单事件,自定义事件。

JavaScript DOM 高级程序设计读书笔记二-LMLPHP

控制事件流和注册事件侦听器

事件流描述的是从页面中接收事件的顺序;事件侦听器,就是一个常规的JavaScript函数。

三个阶段和三个模型

事件冒泡:指的是目标元素的事件方法优先并且会被首先执行,然后,事件会向外传播到每个祖先元素,直至document对象。由Microsoft IE提出的冒泡型事件流;

事件捕获:把优先权赋予最外层的祖先元素,事件相应地被由外向内传播,直至抵达目标元素。由Netscape提出的捕获型事件流;

在W3C DOM2 事件模型中,当目标元素被单击时,首先是经过事件捕获阶段,接着是处于目标阶段,最后是事件冒泡阶段;

JavaScript DOM 高级程序设计读书笔记二-LMLPHP

阻止冒泡

可以在事件对象上调用stopPropagation()方法,对于IE, 需要将事件的cancelBubble属性设置为true。

取消默认动作

与事件流有关的最后一个问题就是默认动作。DOM2 事件规范中提供了使用事件的preventDefault()方法取消默认动作的方式。

注册事件的四种事件模型

1. 嵌入式注册模型

例如:

<a href="http://www.google.com" onclick = "alert('11'); return false;">ie</a>

缺点:使标记混乱不堪

2. 传统的事件模型

例如:

window.onload = function(){}

传统的方法从属于浏览器默认的事件流,没有办法指定是在捕获阶段还是在冒泡阶段调用事件。

3. IE事件模型

例如:

window.attachEvent('onload', function(){});

缺点:只对IE有效,对其他浏览器毫无用处;其次,this 引用的是原始JavaScript函数,而不是附加事件侦听器的那个对象。

4. W3C DOM2 事件模型

DOM2事件规范中包含addEventListener()和removeEventListener()方法,这两个方法接受3个参数(事件,事件侦听器,事件阶段),第三个参数是true表示事件侦听器在捕获阶段内执行,否则,如果为false,则会在冒泡阶段发生(默认是false)。此外,W3C 采取了去掉on前缀的方案,因此所有事件都必须使用事件名称而非传统的方法名称来标识。例如:

window.addEventListener('load', function(e){}, false);
//在W3C的模型中,事件侦听器会取得一个表示事件自身的参数。但在IE中,事件对象被保存在window.event中。

DOM2 事件规范中的Event对象属性和方法

  • type: 是一个包含事件名称的字符串值;
  • target: 是DOM文档中最早调用事件序列的目标对象,IE浏览器提供的是srcElement属性;
  • currentTarget: 是当前正在处理的事件侦听器所在的事件流中的DOM元素;
  • preventDefault(): 取消对象的默认动作,比如:浏览器重定向到一个锚元素的href属性的动作;
  • stopPropagation(): 用于停止事件流的进一步执行,包括捕获阶段,目标对象和冒泡阶段;

DOM2 事件规范中的MouseEvent对象属性

JavaScript DOM 高级程序设计读书笔记二-LMLPHP

处理鼠标相对于文档原点的位置的兼容性处理:

function getPointerPositionInDocument(event) {
let e = event || window.event;
let x = e.pageX || (e.clientX +
document.documentElement.scrollLeft || document.body.scrollLeft);
let y = e.pageY || (e.clientY +
document.documentElement.scrollTop || document.body.scrollTop);
return { 'x': x, 'y': y };
}

处理文档/页面水平/垂直方向滚动的像素值:

/*pageXOffset, pageYOffset 属性是 scrollX, scrollY 属性的别名。window.pageXOffset == window.scrollX; // 总是 true
为了跨浏览器兼容性,请使用 window.pageXOffset 代替 window.scrollX。另外,旧版本的 IE(<9)两个属性都不支持,必须通过其他的非标准属性来解决此问题。
完整的兼容性代码如下:
*/
var supportPageOffset = window.pageXOffset !== undefined;
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
var x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
//代码来自MDN:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/scrollY

动态修改样式和层叠样式表

CSSStyleDeclaration对象

这个对象用于表示一个元素的style属性。

  • cssText: 包含以字符串形式表示的全部规则;
  • parentRule: 将引用CSSStyleRule对象;
  • getPropertyValue(propertyName): 返回一个字符串形式的CSS样式属性值;
  • removeProperty(propertyName): 从声明中移除特定的属性;
  • setProperty(propertyName, value, priority): 用于设置特定CSS属性的值;

将样式置于DOM脚本之外

1. style 属性

当在小范围内修改表现时,你可能会经常使用 HTMLElement 元素的 style 属性来修改其表现。但修改style属性存在如下两个主要问题:

  • 使用 style 属性将设计样式嵌入到行为层的DOM脚本中,并不比在语义标记中使用 style 属性更好。
  • 通过 style 属性只能访问到在元素的style属性中以嵌入方式声明的CSS属性。换句话说,通过style属性无法访问由多重样式层叠表而来或者从父元素继承的任何css属性。

2. setProperty(propertyName, value, priority)

除了可以使用style属性直接设置css属性(例如:element.style.color = 'red';)外,DOM2样式规范为CSSStyleDeclaration对象定义了相应的方法,比如setProperty()就使用固有的带连字符的CSS属性名称和值:例如:element.style.setProperty('background-color', 'red');。但非标准的浏览器(例如IE)不支持这种方法。

3. 基于className切换样式

使用方法:element.className = 'newClassName';,此方法的优点是在所有浏览器中都有效。

访问计算样式

DOM2 样式规范在document.defaultView中包含了一个名叫getComputedStyle()的方法,恰好是为这个目的而设计的。该方法返回一个只读的CSSStyleDeclaration对象,其中包含特定元素的所有计算样式,而不仅仅是以嵌入方式定义的样式。

05-07 15:07