观察者模式

2018-12-04  本文已影响0人  0说
<body>

    观察者模式又叫发布订阅模式,定义了一种一对多关系,
    让多个观察者同时监听某一个主题,
    当这个主题发生改变(触发)的时候通知所有的观察者

    1、功能模块之间的任何变化都不会影响到 另一边 变化 
    2、解藕 减少对象和对象之前的相互引用
    3、对象和对象之间存在一种动态的关系
    4、能够单独扩展以及重用

    每一个程序所负责的代码功能写好之后 订阅下 需要的时候进行发布
    <hr>
    <div class="app">
        <input type="text"><br>
        <button>提交</button>
        <span></span>
        <ul></ul>
    </div>
    
    <script>
        /*
            例:
            程序a 写提交按钮后向ul添加li
            程序b 写计算评论的数量
        */



        // 场景 接手该项目 添加新功能 没办法修改原先的代码 这里就要用到观察者模式

        let observer = (function(){
            let eventObj = {},
                id = -1; // 订阅的时候给每一个对象标示一个ID  方便以后解绑
            return {
                // 订阅方法
                subscription(name, fn){ // 订阅者
                    eventObj[name] || (eventObj[name] = [])
                    let idSign = (++id).toString()
                    eventObj[name].push({
                        id: idSign,
                        fn: fn
                    })

                    return idSign

                },
                // 发布方法
                publish(name){
                    
                    eventObj[name].forEach(item => {
                        item.fn()
                    });
                    // while(length--){
                    //     eventObj[name][length].fn()
                    // }
                },
                // 解除订阅
                unSubscription(name, id){
                    let eObj = eventObj[name],
                        length = eObj.length;

                    eObj.forEach((item, index) =>{
                        if(item.id == id) {
                            eObj.splice(index, 1)
                        }
                    })
                }
            }
        })();

        // 程序a
        (function(){
            let app = document.getElementsByClassName('app')[0],
                inpText = app.getElementsByTagName('input')[0],
                btn = app.getElementsByTagName('button')[0],
                oUl = app.getElementsByTagName('ul')[0];


            let addLi = function(){
                let vale = inpText.value,
                    li = document.createElement('li')
                    li.innerHTML = vale;
                
                 // 此处省略100行代码

                console.log(oUl)
                oUl.appendChild(li)  
            }

            // 订阅
            let id = observer.subscription('addLi', addLi)
            console.log(id)
        })();


        // 程序b
        (function(){
            let app = document.getElementsByClassName('app')[0],
                btn = app.getElementsByTagName('button')[0],
                oUl = app.getElementsByTagName('ul')[0],
                oSpan = app.getElementsByTagName('span')[0],

                addComment = function(){
                    let aLi = oUl.children
                    oSpan.innerHTML = aLi.length
                    // 此处省略100行代码
                }

                // 订阅
                let id = observer.subscription('addComment', addComment)
                observer.unSubscription('addComment', id)
                console.log(id)
        })();



        // 我们要做的是:判断有没有值 有值再让添加
        (function(){
            let inpText = document.getElementsByTagName('input')[0],
                btn = document.getElementsByTagName('button')[0]
            
            btn.addEventListener('click', function(){
                if(inpText.value){
                    // 发布
                    observer.publish('addLi') 
                    observer.publish('addComment') 
                }
            })
        })()

    </script>
</body>

案例

<body>
    <div id="one">1</div>
    <div id='two'>2</div>
    <div id="three">3</div>
    <button id='btn'>点击</button>
    <script>
        let scence = {
            list: {
                dom: [],
                callback: []
            },
            // 订阅 监听
            addListen(el, fn){
                let list = this.list,
                    index = 0;

                for (const key in list) {
                    list[key].push(arguments[index])
                    index ++
                }
            },
            // 执行
            publish(){
                let list = this.list

                    list['dom'].forEach((item, index) =>{
                        this.list['callback'][index].apply(document.querySelector(item), arguments)
                    })
            }
        }

        // 订阅
        scence.addListen('#one', function(){
            this.style.border = '1px solid red'
        })

        scence.addListen('#two', function(){
            this.style.color = 'red'
        })

        scence.addListen('#three', function(){
            this.style.backgroundColor = 'yellow'
        })
        
        
        // 执行
        btn.onclick = function(){
            scence.publish()
        }
        


    
    </script>
上一篇下一篇

猜你喜欢

热点阅读