外观模式(Faceade):为一组复杂的子系统接口提供一个更高级的统一接口,通过这个接口使得对子系统接口的访问更容易。
在 JavaScript 中有时也会用于对底层结构兼容性做统一封装来简化用户使用。

一,添加一个点击事件

为页面文档 document 对象绑定一个 click 事件来实现隐藏提示框的交互功能。

  1. document.onclick = function(e) {
  2. e.preventDefault();
  3. if (e.target !== document.getElementById('myinput')) {
  4. hidePageAlert();
  5. }
  6. }
  7. function hidePageAlert() {
  8. // 隐藏提示框
  9. }

“首先,你为 document 绑定了 onclick 事件,但是 onclick 是 DOM 0 级事件,相当于为元素绑定一个事件方法。所以我们团队有人再次使用 document 绑定 click 事件时,会将你定义的方法覆盖掉。”

“所以,你应该用 DOM 2 级事件 addEventListener 来实现。但老版本的 IE 浏览器(低于 IE9 )不支持这个方法,要用 attachEvent。当然如果有不支持 DOM 2 级事件的浏览器,只能用 onclick。”

二,兼容方式

在 JavaScript 中可以通过一个”套餐“来简化复杂的需求,比如我们同一功能接口方法的不统一,我们可以通过外观模式来定义一个统一的接口方法。
这样就提供了一个更简单的高级接口。

  1. // 使用外观模式封装事件绑定
  2. function addEvent(dom, type, fn) {
  3. if (dom.addEventListener) {
  4. dom.addEventListener(type, fn, false);
  5. } else if (dom.attachEvent) {
  6. dom.attachEvent('on' + type, fn);
  7. } else {
  8. dom['on' + type] = fn;
  9. }
  10. }
  11. // 使用
  12. var myinput = document.getElementById('myinput');
  13. addEvent(myinput, 'click', function() {
  14. console.log('绑定事件');w
  15. })

三,除此之外

外观模式可以简化底层接口复杂性,也可以解决浏览器兼容性问题。
另外两处问题是,在 IE 低版本浏览器中不兼容 e.preventDefault() 和 e.target。

  1. // 获取事件对象
  2. var getEvent = function(event) {
  3. // 标准浏览器返回 event,IE 下 window.event
  4. return event || window.event;
  5. }
  6. // 获取元素
  7. var getTarget = function(event) {
  8. var event = getEvent(event);
  9. // 标准浏览器下 event.target,IE 下 event.srcElement
  10. return event.target || event.srcElement;
  11. }
  12. // 阻止默认行为
  13. var preventDefault = function(event) {
  14. var event = getEvent(event);
  15. // 标准浏览器
  16. if (event.preventDefault) {
  17. event.preventDefault()
  18. } else {
  19. event.returnValue = false;
  20. }
  21. }

之前代码,处理如下:

  1. document.onclick = function(e) {
  2. preventDefault(e)
  3. if (getTarget(e) !== document.getElementById('myinput')) {
  4. hidePageAlert();
  5. }
  6. }
  7. function hidePageAlert() {
  8. // 隐藏提示框
  9. }