Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Einführung in das Beobachtermuster von JavaScript-Entwurfsmustern

Detaillierte Einführung in das Beobachtermuster von JavaScript-Entwurfsmustern

高洛峰
高洛峰Original
2017-03-20 11:03:431305Durchsuche

Javascript ist in einer ereignisgesteuerten Umgebung aktiv, z. B. bei Mausreaktionen, Ereignisrückrufen, Netzwerkanforderungen usw. Der 观察者-Modus, auch bekannt als 发布者-订阅者(publisher-subscriber)模式, verwaltet die Beziehung zwischen Objekten, deren Verhalten und Zuständen. und verwaltet die Beziehung zwischen Menschen und Aufgaben.

1. Das häufigste Beobachtermuster

1.1 Ereignis-Listener
document.body.addEventListener('click', function () {
    console.log('you clicked me, poor guy!')
});

Dies ist das einfachste und häufigste Beobachtermuster, außer click Zusätzlich zu load, blur, drag, focus, mouseover usw. Ein Ereignis-Listener (Listener) unterscheidet sich von einem Ereignis-Handler (Handler). Bei einem Ereignis-Listener kann ein Ereignis mehreren Listenern zugeordnet werden, und jeder Listener ist für die Ausführung und Verarbeitung des Ereignisses verantwortlich . Nach der zugehörigen Funktion kann ein Ereignis eine Handlerfunktion haben:

var dom = $('.dom');
var listener1 = function(e){
    //do one thing
}
var listener2 = function(e){
    //do another thing
}
addEvent(dom,'click',listener1);
addEvent(dom,'click',listener2);

In diesem Beispiel eines Ereignis-Listeners sind sowohl listener1 als auch listener2 Listener für dom-Elemente. ihre jeweiligen Funktionen werden ausgeführt;

var dom = document.getElementById('dom');
var handler1 = function(e){
    //do one thing
}
var handler2 = function(e){
    //do another thing
}
dom.onclick = handler1;
dom.onclick = handler2;

Im Beispiel dieses Ereignishandlers wird handler1 nicht ausgeführt, sondern nur handler2, was eine Zuweisungsoperation ist.

1.2 Animation

Der Beobachtermodus wird häufig in der Animation verwendet. Der Beginn, der Abschluss, die Pause usw. der Animation erfordern, dass ein Beobachter das Verhalten und den Status des Objekts bestimmt.

//定义动画
var Animation = function(){
    this.onStart = new Publisher;  //关于Publisher的设计将在1.3节介绍
    this.onComplete = new Publisher;
    this.onTween = new Publisher;
}
//定义一个原型方法
Animation.prototype.look = function(){
    this.onStart.deliver('animation started!');
    this.onTween.deliver('animation is going on!');
    this.onComplete.deliver('animation completed!');  
};

//实例一个box对象
var box = new Animation();

//定义三个函数作为subscribers
var openBox = function(msg){
    console.log(msg)
}
var checkBox = function(msg){
    console.log(msg)
}
var closeBox = function(msg){
    console.log(msg)
}

//订阅事件
openBox.subscribe(box.onStart);
checkBox.subscribe(box.onTween);
closeBox.subscribe(box.onComplete);

//调用方法
box.look()

//animation started!
//animation is going on!
//animation completed!

1.3 Aufbau des Beobachters

Zuerst wird ein Herausgeber benötigt. Definieren Sie zunächst einen Konstruktor und ein Array zum Speichern von Abonnenteninformationen:

function Publisher(){
    this.subscribes = [];
}

Der Herausgeber hat die Funktion, Nachrichten zu veröffentlichen, und definiert eine Prototypfunktion für die Zustellung:

Publisher.prototype.deliver = function(data){
    this.subscribes.forEach(function(fn){
        fn(data);
    });
    return this;
}

Nächster Erstellen Sie die Abonnementmethode:

Function.prototype.subscribe = function(publisher){
    var that = this;
    var alreadyExists = publisher.subscribes.some(function(el){
        return el === that;
    });
    if(!alreadyExists){
        publisher.subscribes.push(this);
    }
    return this;
}

Fügen Sie die Abonnementmethode direkt zum Funktionsprototyp hinzu, damit alle Funktionen diese Methode aufrufen können. Auf diese Weise ist die Konstruktion abgeschlossen. Informationen zu den Verwendungsmethoden finden Sie im Anwendungsfall von 1.2 Animation.
Eine intuitivere Erklärung (nehmen Sie onStart als Beispiel): Wenn das box-Objekt die look-Methode ausführt, führen Sie onStart.deliver() aus, veröffentlichen Sie das onStart-Ereignis und senden Sie es Benachrichtigung'animation started!', zu diesem Zeitpunkt hört onStart, der openBox abgehört hat, die durch das Ereignis veröffentlichten Informationen ab und druckt sie aus.

1.4 Eine andere Möglichkeit, einen Beobachter zu erstellen

Diese Methode imitiert den Ereignisverarbeitungsmechanismus von NodeJS und der Code ist relativ prägnant:

    var scope = (function() {
    //消息列表
    var events = {};
    return {
        //订阅消息
        on:function(name,hander){
            var index = 0;  //记录消息时间的索引
            if(events[name]){  
                //消息名已存在,将处理函数放到该消息的事件队列中
                index = events[name].push(hander) - 1; 
            }else{
                events[name] = [hander];
            }
            //返回当前消息处理事件的移除函数
            return function(){
                events[name].splice(index,1);
            }
        },
        //关闭消息
        off:function(name){
            if(!events[name]) return;
            //消息存在,删除消息
            delete events[name];
        },
        //消息发布
        emit:function(name,msg){
            //消息不存在,不处理
            if(!events[name]) return;
            //消息存在,将该事件处理队列中每一个函数都执行一次
            events[name].forEach(function(v,i){
                v(msg);
            });
        }
    }
})();

var sayHello = scope.on('greeting',function(msg){
    console.log('订阅消息:' + msg);
});

var greeting = function(msg){
    console.log('发布消息:' + msg);
    scope.emit('greeting', msg);
}

greeting('hello Panfen!')

1.5 Beobachtung in NodeJS Implementierung Plan des Beobachtermodus

Es gibt ein Ereignismodul in Nodejs, um den Beobachtermodus zu implementieren. Informationen zum Beobachtermodus finden Sie in Nodejs. Die meisten Module verfügen über ein integriertes Ereignismodul, sodass Sie Emit direkt starten können Ereignisse. und weiter, um auf Ereignisse zu warten, oder definieren Sie es zuerst wie folgt;

var EventEmitter = require('events').EventEmitter;
var life = new EventEmitter();
life.setMaxListeners(11);       //设置最大监听数,默认10

//发布和订阅sendName
life.on('sendName',function(name){
    console.log('say hello to '+name);
});
life.emit('sendName','jeff');

//发布和订阅sendName2
function sayBeautiful(name){
    console.log(name + ' is beautiful');
}
life.on('sendName2',sayBeautiful);
life.emit('sendName2','jeff');

hasConfortListener: wird verwendet, um zu bestimmen, ob das ausgegebene Ereignis vorliegt ein Zuhörer
  • removeListener: Entfernen Sie den Zuhörer
  • listenerCount: Die Gesamtzahl aller Zuhörer für dieses Ereignis
  • removeAllListeners: Alle (oder einen) Listener des Ereignisses entfernen
  • 1.6 Zusammenfassung
Das Beobachtermuster legt die Logik von

und

fest , anwendbar Für Situationen, in denen Sie menschliches Verhalten vom Anwendungsverhalten trennen möchten. Beispiel: Wenn der Benutzer auf eine Registerkarte in der Navigationsleiste klickt, wird ein Untermenü mit weiteren Optionen geöffnet. Im Allgemeinen entscheidet sich der Benutzer dafür, das Klickereignis direkt anzuhören. Der Nachteil dabei ist, dass dies nicht der Fall ist das Gleiche wie beim Klickereignis. Die Ereignisse sind direkt miteinander verknüpft. Ein besserer Ansatz besteht darin, ein beobachtbares onTabChange-Objekt zu erstellen und mehrere Beobachterimplementierungen zuzuordnen.

推送Verwandte Artikel: 收听

Detaillierte Erklärung des klassischen JavaScript-Entwurfsmusters, des Strategiemusters

Das klassische JavaScript-Entwurfsmuster, das Einfache Beispiel für einen Factory-Mustercode

Detaillierte Erläuterung des klassischen JavaScript-Designmuster-Singleton-Musters

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in das Beobachtermuster von JavaScript-Entwurfsmustern. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn