响应用户操作和事件

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

事件的类型

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

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

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

三个阶段和三个模型

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

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

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



阻止冒泡

可以在事件对象上调用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对象属性



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

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对象,其中包含特定元素的所有计算样式,而不仅仅是以嵌入方式定义的样式。

JavaScript DOM 高级程序设计读书笔记二的更多相关文章

  1. JavaScript DOM 高级程序设计读书笔记一

    创建可重用的对象 简而言之,对象就是包含一组变量(称为属性)和函数(称为方法)的集合的实例.对象通常由类派生而来,而类中定义了对象拥有的属性和方法.如果你的脚本中都是对象之间的交互操作,那么就可以称之 ...

  2. JavaScript DOM编程艺术读书笔记(二)

    第五章 最佳实践 平稳退化(graceful degradation):如果正确使用了JavaScript脚本,可以让访问者在他们的浏览器不支持JavaScript的情况下仍能顺利地浏览你网站.虽然某 ...

  3. javascript高级程序设计读书笔记-事件(一)

    读书笔记,写的很乱   事件处理程序   事件处理程序分为三种: 1.html事件2. DOM0级,3,DOM2级别  没有DOM1 同样的事件 DOM0会顶掉html事件   因为他们都是属性  而 ...

  4. AngularJS高级程序设计读书笔记 -- 大纲篇

    零. 初衷 现在 AngularJS 4 已经发布了, 楼主还停留在 1.x 的阶段, 深感自卑. 学习 AngularJS 的初衷是因为, 去年楼主开始尝试使用 Flask 开发自动化程序, 需要用 ...

  5. Javascript高级程序设计读书笔记(第10章 DOM)

    第10章 DOM 10.1  节点层次 每个节点都有一个nodeType属性,用于表明节点的类型.任何节点类型必是下面中的一个: Node.Element_NODE(1); NODE.ATTRIBUT ...

  6. Javascript高级程序设计--读书笔记之面向对象(二)

    前面讲了面向对象的封装,这章我们就来说一说继承 1.原型链 实现原型链有一种基本模式,其代码大概如下 <script> function SuperType(){ this.propert ...

  7. javascript高级程序设计读书笔记

    第2章  在html中使用javascript 一般都会把js引用文件放在</body>前面,而不是放在<head>里, 目的是最后读取js文件以提高网页载入速度. 引用js文 ...

  8. JavaScript高级程序设计-读书笔记(7)

    第22章 高级技巧 1.高级函数 (1)安全的类型检测 在任何值上调用Object原生的toString()方法,都会返回一个[object NativeConstructorName]格式的字符串. ...

  9. JavaScript高级程序设计 读书笔记

    第一章 JavaScript 简介 第二章 Html中使用JavaScript 第三章 基本概念 第四章 变量,作用域,内存 第五章 引用类型 第六章 面向对象 第七章 函数表达式 第八章 BOM 第 ...

随机推荐

  1. Uncaught ReferenceError: jQuery is not defined

    页面调试时,明明引入了JQ文件,却一直提示Uncaught ReferenceError: jQuery is not defined错误. 转自:http://blog.csdn.net/baicp ...

  2. [代码笔记]JS保持函数单一职责,灵活组合

    比如下面的代码,从服务端请求回来的订单数据如下,需要进行以下处理1.根据 status 进行对应值得显示(0-进行中,1-已完成,2-订单异常)2.把 startTime 由时间戳显示成 yyyy-m ...

  3. servlet doGet()方法获取字符串乱码问题

    当你遇到ajax向servlet发送数据出现乱码问题的时候不要惊慌,现有以下两个解决办法 (1)在doGet和doPost方法中添加以下代码 request.setCharactersEncoding ...

  4. CRM实施失败?请注意这6大问题及对策!

    据Gartner调查显示:约50%的CRM项目不能达到客户期望.这一点与很多其他的IT项目状况非常类似,大多出于管理问题,供应商服务能力,项目执行不善等. 另据一个在线CRM论坛调查其失败的原因:67 ...

  5. 应用shell脚本停启Tomcat

    最近在工作中频繁的操作多个tomcat,顺便就简单研究了一下 一. 简介 Shell 是一种与操作系统直接交互的程序,Unix系统中叫Bourne Shell,包括以下几种 Sh—Bourne She ...

  6. rabbitmq之确保消息不丢失

    1.背景引入 在使用消息中间件(rabbitmq)时,令开发者最头痛的就是防止消息丢失问题,而消息丢失可能发生的位置主要为三种,分别为(1)消息发送到MQ中消费者消费未成功时突然宕机:(2)消息发送到 ...

  7. Redis与Memocache的区别

    转载地址:http://gnucto.blog.51cto.com/3391516/998509 Redis与Memcached的区别 传统MySQL+ Memcached架构遇到的问题 实际MySQ ...

  8. Django的URL调度

    1.URLconf (URL configuration):(Django版本1.11.20,其它版本可能各有差异.) 在Django中Python后端与前端URL进行交互,是通过一个名为urlcon ...

  9. Why Ambari is setting the security protocol of the kafka to PLAINTEXTSASL instead of SASL_PLAINTEXT?

    首页 / Data Ingestion & Streaming / Why Ambari is setting the security protocol of the kafka to PL ...

  10. SpringBoot中使用JNnit4(一)之Mockito的使用

    经过入门篇,可以编写出一个简单的测试用例. 这篇讲的是BDDMockito的使用. BDDMockito用于测试时进行打桩处理:通过它可以指定某个类的某个方法在什么情况下返回什么样的值. 在单元测试时 ...