第九章 外观模式

85 阅读2分钟

外观模式(Faceade):为一组复杂的子系统接口提供一个更高级的统一接口,通过这个接口使得对子系统接口的访问更容易。

在 JavaScript 中有时也会用于对底层结构兼容性做统一封装来简化用户使用。

添加一个点击事件

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

document.onclick = function(e) {
	e.preventDefault();
  if (e.target !== document.getElementById('myinput')) {
  	hidePageAlert();
  }
}

function hidePageAlert() {
    // 隐藏提示框
}

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

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

兼容方式

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

这样就提供了一个更简单的高级接口

// 使用外观模式封装事件绑定
function addEvent(dom, type, fn) {
	if (dom.addEventListener) {
  	dom.addEventListener(type, fn, false);
  } else if (dom.attachEvent) {
  	dom.attachEvent('on' + type, fn);
  } else {
  	dom['on' + type] = fn;
  }
}

// 使用
var myinput = document.getElementById('myinput');
addEvent(myinput, 'click', function() {
	console.log('绑定事件');w
})

除此之外

外观模式可以简化底层接口复杂性,也可以解决浏览器兼容性问题。

另外两处问题是,在 IE 低版本浏览器中不兼容 e.preventDefault() 和 e.target。

// 获取事件对象
var getEvent = function(event) {
	// 标准浏览器返回 event,IE 下 window.event
  return event || window.event;
}

// 获取元素
var getTarget = function(event) {
	var event = getEvent(event);
  // 标准浏览器下 event.target,IE 下 event.srcElement
  return event.target || event.srcElement;
}

// 阻止默认行为
var preventDefault = function(event) {
	var event = getEvent(event);
  // 标准浏览器
  if (event.preventDefault) {
    event.preventDefault()
  } else {
  	event.returnValue = false;
  }
}

之前代码,处理如下:

document.onclick = function(e) {
	preventDefault(e)
  if (getTarget(e) !== document.getElementById('myinput')) {
  	hidePageAlert();
  }
}

function hidePageAlert() {
    // 隐藏提示框
}