常用设计模式
1.外观模式
外观模式一般用于对复杂底层代码的封装,暴漏一个高级的统一接口,解决一些类似浏览器兼容性的问题。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> #root { width: 300px; height: 200px; background-color: #ff0; } </style> </head> <body> <div id="root"> test </div> <script> /* 下面方法实现给document绑定多个事件,不能用on事件 当单击root时正常,单击之外的弹出信息 */ var ele = document.getElementById('root'); // 第一个外观模式封装的函数,解决浏览器兼容问题 function addEvent(el, type, fn) { if (el.addEventListener) { // 如果支持addEventListener DOM2级 el.addEventListener(type, fn, false); } else if (el.attachEvent) { // IE9-等 DOM2级 el.attachEvent('on' + type, fn); } else { // 以上两种都不支持 el['on' + type] = fn; // DOM1级事件,重复定义会被覆盖 } } // 第二个外观模式封装的函数 function definePreventDefault(event) { if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; // IE } } // 第三个外观模式封装的函数 function getTarget(event) { return event.target || event.srcElement; // IE是event.srcElement } function doSth(text) { // e.preventDefault(); ---IE低版本不支持 // if (e.target !== ele) { // TODO } --- e.target的IE低版本不支持 return function(e) { const event = e || window.event; // 低版本IE下是window.event definePreventDefault(event); console.log(getTarget(event)) if (getTarget(e) !== ele) { alert(text) } } } addEvent(document, 'click', doSth("哼")) addEvent(document, 'click', doSth("哈")) addEvent(document, 'click', doSth("呵")) </script> </body> </html>
css内联样式值的获取也存在IE9-的兼容性问题
// IE9-支持currentStyle function getStyleCss(ele, cssName) { return ele.currentStyle ? ele.currentStyle[cssName] : getComputedStyle(ele, null)[cssName] }
2. 单例模式
单例模式的应用有两种。
一种是定义命名空间,将某一类或者某一模块的方法放到一个对象中,避免声明的方法变量名称重复,也避免全局污染;
// 注意想要使用单例模式里面定义的方法,一定要使用命名空间(LyraFuncs)或者this var LyraFuncs = { a: function(x,y) { }, b: function(z) { return LyraFuncs.a(1,2) // 或者 return this.a(1,2) }, }
一种是惰性单例,就是对象类只允许实例化一次,并且在需要的时候再实例化。
// 比如mobx的model里的变量在多个地方会使用,并且彼此互相关联 // 那么此时只需要实例化一次,而且等需要的时候再去实例化,节约系统资源 var LazySingle = (function IIFE() { let _instance = null; // 闭包,变量不会被释放掉 class Single { constructor() { this.a = '5'; } } return function() { if (!_instance) { _instance = new Single(); } return _instance; } })(); // 调用的时候用法 console.log(LazySingle().a); // '5'
3.适配器模式
适配器模式主要用途有两种。
1)代码更换插件或者库后,需要兼容原来的代码逻辑。
2)适配数据。当参数数据,或者后台返回的数据不是我们希望的数据时,进行数据适配,返回需要的数据格式。