由重构进阶前端开发入门 (二) 事件与事件对象
掌握 DOM 的基本概念后,这次我们讲讲浏览器的事件和事件对象。再结合具体业务需求,通过例子展示事件相关的操作方法。
相关文章:
事件与事件对象
事件与 DOM
1. 从最初的“点击”开始
“点击这个按键时,XXX 变成 YYY,然后……”
新手最初学会的,基本是这样使用 onclick
事件属性进行处理:
1 | <button onclick="alert('Hello world!')">Button</button> |
或者对复杂些的处理,绑定全局函数:
1 | <span id="txt_info"></span> |
2. 新的处理方式
网上古老的 JS 入门教程可能都是这么写的。
不过,二十年来业务不断进化,这样的处理方式虽然还被浏览器所支持,但暴露出越来越多问题,已经不再建议使用了。
一是这种方式只能绑定一个处理函数,且不能取消绑定不够灵活;二是全局函数容易混淆,项目到达一定规模后容易失控,导致意外。
W3C 标准推荐使用 DOM 对象的 addEventListener
和 removeEventListener
方法来绑定和取消绑定处理函数。
1 | <span id="txt_info"></span> |
低版本 IE 浏览器使用了自家的另一套事件相关方法,已经随着浏览器标准迭代被废弃,这里不再赘述。
不过日常需要对 IE8 这一类浏览器进行支持时,一般使用 jQuery 等现成做好了兼容性处理的框架,使用方便快捷,API 也是一目了然,非常容易理解。
上述代码在使用 jQuery 的时候可以写作:
1 | <span id="txt_info"></span> |
3. DOM 对象与 jQuery 对象
上面 jQuery 的代码和之前的原生 JS 代码等效,但有一点需要注意,也是新手经常混淆的。
$('<css选择器>')
的效果是根据 CSS 选择器找到页面上对应的元素,返回的对象可以对其做绑定事件处理器等操作,如上面的 $.fn.on
(即 $(...).on
)。
但是仔细观察这个返回对象,你会发现它并不是原生的 DOM 对象,对它做原生 DOM 相关的操作时会发现它并不支持原生 DOM 相关的 API。
1 | $('#txt_info').textContent = new Date(); // × - 无效 |
它其实是一个特殊数组,里面存放着传入 CSS 选择器所对应的所有 DOM 对象,通过 .length
可以查看其中选中的元素数量,通过数组下标可以取出其中的原生 DOM 对象:
1 | $('#text_info').length; // => 1 |
当 jQuery 选择了多个元素时,各类 API 操作可以对立面所有成员进行处理,非常方便:
1 | $('blockquote').prepend('<span>“</span>'); // 所有 blockquote 元素内容前插入 “ 符号 |
4. 常用 jQuery API
- 选择元素和创建元素使用
$()
,find
,filter
- 处理事件使用
on
,off
,trigger
- 操作元素内容使用
text
,html
- 操作元素位置和尺寸使用
offset
,width
,height
- 操作元素属性/特性使用
prop
,attr
,removeProp
,removeAttr
- 操作元素样式/
className
时使用css
,addClass
,removeClass
,toggleClass
,hasClass
- 父元素插入/追加/移除子元素使用
prepend
,append
- 子元素附近插入/查找邻近元素使用
prev
,next
,prevAll
,nextAll
- 子元素移除时使用
remove
- 查找父元素/祖先元素使用
parent
,parents
掌握上述最常用也是最基本的 API 的使用方法和对应场景后,就可以实现 90% 以上的日常业务需求了。
事件对象 e
由于原生 DOM API 写起来太过繁琐,以及兼容性的处理太过复杂,这里推荐使用 jQuery 等现成框架,业余时间再对常见的兼容性进行了解,以便遇到意外时知道问题出在何处。
当我们对页面元素绑定了事件处理器后,常常会看到一个神秘的 e
参数:
1 | $('#btn_update').on('click', function (e) { |
它就是所谓的“事件对象”了,不过上面的例子里似乎并没有用上它啊?它到底有什么作用呢?
个人理解是,“事件”就是用户操作、浏览器状态变化这些正在发生的事情;而“事件对象”就是这个“事件”发生的相关信息。
比如用户点击按键 #btn_update
后,触发了点击事件 click
,事件的监听函数接收到的事件对象 e
就会包含这次点击的相关信息,如点击坐标、发起元素、传递路径等等。
此外,事件对象 e
还提供了一些 API 可以对这次事件进行一些附加操作,下面进行具体说明。
例子:幻灯片切换效果(点击位置判断)
过去对于用户点击图片区域判断,需要通过 img 元素的 usemap 属性实现,使用方式较为复杂,且限制较多,可复用性低。
现在,实现一个简单的幻灯片点击切换效果,只需根据事件对象中相关参数来判断即可。
大致效果是:用户点击左右两侧 20% 区域时,切换展示上/下一章图片;点击中间区域不处理。
1 |
|
只需要对列表元素绑定点击事件,然后根据点击位置和列表宽度,就能判断出用户点击的区域,然后做样式切换即可:
1 | // 1. 选择 .pic-list 元素,绑定 click 事件监听器 |
上述代码用原生 JS 写会复杂很多,因为需要离开 jQuery 编写兼容 IE8 的代码,需要对事件绑定、事件对象获取、元素查找、点击坐标、元素坐标等操作做大量兼容处理。做兼容处理的代码甚至会比主要逻辑代码还要多得多。
有兴趣的同学课余可以尝试一下,使用原生 JS 兼容 IE8 和现代浏览器后,再对比上述代码,就能明白 jQuery 的强大之处了~
附:可用的跨浏览器兼容的 jQuery 标准化事件属性
jQuery 按照 W3C 标准规范,将不同浏览器的事件对象处理成了同一格式,免去了日常业务层反复做浏览器兼容的繁琐工作。
大部分属性只需要参考 W3C 规范即可,各属性具体说明可阅读 jQuery 的 API 文档进行了解:
中文文档:jQuery | 事件对象