JavaScript设计模式——结构型设计模式之外观模式

214 阅读2分钟

结构型设计模式:将类或对象组合,简化设计

外观模式概念:为一组复杂的子系统接口提供一个更高级的统一接口。

简而言之: 统一接口,方便调用(套餐服务)

应用: 兼容方法封装,简化底层操作

1.1 简化底层接口案例 --- 点击事件

情景说明: 在一个dom元素上绑定多个onClick事件, 后者会覆盖前者,只执行后面的事件,这是该怎么办?

简单的解决方案:

addEventListener

这个方法绑定多个click 事件都会顺序执行不会被覆盖(像队列一样,先绑定的先执行)

<!--实例代码-->
<div id="app">
    <button id="btn">点击</button>
</div>
//IE 8 测试  不能使用let
var btn = document.getElementById('btn')
var fn1 = function() {
    alert('fn1')
}
var fn2 = function() {
    alert('fn2')
}
btn.addEventListener('click', fn1)
btn.addEventListener('click', fn2)

但是这个方法存在兼容性问题,低于IE9是不支持这个方法的。所以此处显示出外观模式的作用,利用该模式设计统一调用的接口,简化因为兼容性原因接口不统一的问题 --- 简化底层接口复杂性 image.png 利用观察模式封装绑定方法接口

<div id="app">
    <button id="btn">点击</button>
</div>
        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 btn = document.getElementById('btn');
        var fn1 = function() {
            alert('fn1');
        };
        var fn2 = function() {
            alert('fn2');
        };
        addEvent(btn, 'click', fn1);
        addEvent(btn, 'click', fn2);

tip 需要了解一下DOM0,DOM2

1.2 简化底层接口案例 --- 通过外观模式封装多个功能

<div id="app">
</div>
<script>
    var A = {
        getDom: function(id) {
            return document.getElementById(id)
        },
        setStyle: function(dom, key, value) {
            dom.style[key] = value
        },
        // getStyle: function(dom, key) {
        //     return dom.style[key]
        // },
        setAttr: function(dom, key, value) {
            dom.setAttribute(key, value)
        },
        setText: function(dom, text) {
            dom.innerText = text
        }
    }
    //test
    var app = A.getDom('app')
    A.setText(app, '你好')
    A.setAttr(app, 'data-id', 'uuid')
    A.setStyle(app, 'background', 'yellow')
</script>

1.3 兼容性案例

目的: 实现阻止默认事件,需要兼容到IE8

//在div 中阻止 a链接默认跳转行为
 <div id="app">
        <a href="https://www.baidu.com" id="link">百度</a>
    </div>
        var getEvent = function(e) {
            // 标准浏览器 event  IE  window.event
            return e || window.event
        }
        var getTarget = function(e) {
            // console.log(e)
            // 标准浏览器 e.target IE e.srcElement
            return  e.target || e.srcElement
        }
        // 阻止默认行为
        var preventDefault = function(e) {
            var event = getEvent(e);
            if (event.preventDefault) {
                event.preventDefault();
            } else {
                // IE
                event.returnValue = false;
            }
        }
        var div = document.getElementById('app');
        var targetDom = document.getElementById('link');
        document.onclick = function(e) {
            preventDefault(e);
            if (getTarget(e) === targetDom) {
                alert('preventDefault');
            }
        }

实践 封装一个获取CSS样式的方法

<div id="app">

    </div>
    <script>
        var getStyle = function(id, key) {
            return document.getElementById(id).style[key];
        }
        console.log(getStyle('app', 'backgroundColor'));
        var getCss =  function(dom, attr) {
            if (dom.currentStyle) {
                // IE
                return dom.currentStyle[attr];
            } else {
                return window.getComputedStyle(dom, false)[attr];
            }
        }
        var dom = document.getElementById('app');
        console.log(getCss(dom, 'background-color'));
    </script>