常用设计模式

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)适配数据。当参数数据,或者后台返回的数据不是我们希望的数据时,进行数据适配,返回需要的数据格式。

 

posted @ 2019-09-11 15:55  Lyra李  阅读(145)  评论(0编辑  收藏  举报