MVC-Muster ist ein Software-Architekturmuster in der Softwareentwicklung. Das Softwaremuster ist im Allgemeinen in drei Teile unterteilt: Modell, Ansicht und Controller;
Modell: Das Modell wird verwendet, um Daten im Zusammenhang mit der Geschäftslogik der Anwendung und Methoden zur Datenverarbeitung zu kapseln. Modelle haben direkten Zugriff auf die Daten. Das Modell ist nicht auf „Ansicht“ und „Controller“ angewiesen, was bedeutet, dass es dem Modell egal ist, wie die Seite angezeigt und bedient wird.
Ansicht: Das Wichtigste der Ansichtsebene besteht darin, die Datenänderungen auf der Modellebene zu überwachen und die HTML-Seite in Echtzeit zu aktualisieren. Natürlich umfasst es auch einige Ereignisregistrierungs- oder Ajax-Anforderungsvorgänge (Veröffentlichen von Ereignissen), die alle in der Ansichtsebene ausgeführt werden.
Controller: Der Controller empfängt die Operation des Benutzers. Das Wichtigste ist, die Ereignisse der Ansichtsebene zu abonnieren und dann das Modell oder die Ansicht aufzurufen, um die Operation des Benutzers abzuschließen Seite, der Controller gibt nichts aus und antwortet. Die Seite führt keine Verarbeitung durch, sondern empfängt lediglich die Anfrage und entscheidet, welche Methode im Modell aufgerufen werden soll, um die Anfrage zu verarbeiten, und bestimmt dann, welche Methode in der Ansicht aufgerufen werden soll, um die zurückgegebenen Daten anzuzeigen .
Lassen Sie uns ein einfaches Dropdown-Box-Steuerelement implementieren, das wir wie in der Abbildung unten gezeigt hinzufügen und löschen können:
Der Code lautet wie folgt:
/* 模型用于封装与应用程序的业务逻辑相关的数据以及对数据处理的方法。模型有对数据直接访问的权利。 模型不依赖 "视图" 和 "控制器", 也就是说 模型它不关心页面如何显示及如何被操作. */ function Mode(elems) { // 所有元素 this._elems = elems; // 被选中元素的索引 this._selectedIndex = -1; // 增加一项 this.itemAdd = new Event(this); // 删除一项 this.itemRemoved = new Event(this); this.selectedIndexChanged = new Event(this); } Mode.prototype = { constructor: 'Mode', // 获取所有的项 getItems: function(){ return [].concat(this._elems); }, // 增加一项 addItem: function(elem) { this._elems.push(elem); this.itemAdd.notify({elem:elem}); }, // 删除一项 removeItem: function(index) { var item = this._elems[index]; this._elems.splice(index,1); this.itemRemoved.notify({elem:item}); if(index === this._selectedIndex) { this.setSelectedIndex(-1); } }, getSelectedIndex: function(){ return this._selectedIndex; }, setSelectedIndex: function(index){ var previousIndex = this._selectedIndex; this._selectedIndex = index; this.selectedIndexChanged.notify({previous : previousIndex}); } }; /* 下面是观察者模式类,它又叫发布---订阅模式;它定义了对象间的一种一对多的关系, 让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。 */ function Event(observer) { this._observer = observer; this._listeners = []; } Event.prototype = { constaructor: 'Event', attach : function(listeners) { this._listeners.push(listeners); }, notify: function(objs){ for(var i = 0,ilen = this._listeners.length; i ) { this._listeners[i](this._observer,objs); } } }; /* * 视图显示模型数据,并触发UI事件。 */ function View(model,elements){ this._model = model; this._elements = elements; this.listModified = new Event(this); this.addButtonClicked = new Event(this); this.delButtonClicked = new Event(this); var that = this; // 绑定模型监听器 this._model.itemAdd.attach(function(){ that.rebuildList(); }); this._model.itemRemoved.attach(function(){ that.rebuildList(); }); // 将监听器绑定到HTML控件上 this._elements.list.change(function(e){ that.listModified.notify({index: e.target.selectedIndex}); }); // 添加按钮绑定事件 this._elements.addButton.click(function(e){ that.addButtonClicked.notify(); }); // 删除按钮绑定事件 this._elements.delButton.click(function(e){ that.delButtonClicked.notify(); }); } View.prototype = { constructor: 'View', show: function(){ this.rebuildList(); }, rebuildList: function(){ var list = this._elements.list, items, key; list.html(""); items = this._model.getItems(); for(key in items) { if(items.hasOwnProperty(key)) { list.append('' +items[key]+ ''); } } this._model.setSelectedIndex(-1); } }; /* 控制器响应用户操作,调用模型上的变化函数 负责转发请求,对请求进行处理 */ function Controller(model,view) { this._model = model; this._view = view; var that = this; this._view.listModified.attach(function(sender,args){ that.updateSelected(args.index); }); this._view.addButtonClicked.attach(function(){ that.addItem(); }); this._view.delButtonClicked.attach(function(){ that.delItem(); }); } Controller.prototype = { constructor: 'Controller', addItem: function(){ var item = window.prompt('Add item:', ''); if (item) { this._model.addItem(item); } }, delItem: function(){ var index = this._model.getSelectedIndex(); if(index !== -1) { this._model.removeItem(index); } }, updateSelected: function(index){ this._model.setSelectedIndex(index); } };
Der HTML-Code lautet wie folgt:
<select id="list" size="10" style="width: 10rem">select>br/> <button id="plusBtn"> + button> <button id="minusBtn"> - button>
Der Seiteninitialisierungscode lautet wie folgt:
$(function () { var model = new Mode(['PHP', 'JavaScript']), view = new View(model, { 'list' : $('#list'), 'addButton' : $('#plusBtn'), 'delButton' : $('#minusBtn') }), controller = new Controller(model, view); view.show(); });
Die Codeanalyse ist wie folgt:
Lassen Sie uns zunächst analysieren, welche Art von Funktionen wir erreichen möchten. Die Grundfunktionen sind:
Ein Dropdown-Feld, das es dem Benutzer ermöglicht, ein Element hinzuzufügen und zu löschen, nachdem er es durch Benutzereingabevorgänge ausgewählt hat;
Natürlich wird auch das Ereignis für den Benutzer zum Wechseln zu diesem Element hinzugefügt
Wenn wir jetzt beispielsweise ein Datenelement hinzufügen, fügen Sie ein Listening-Ereignis auf der Ansichtsebene hinzu, wie im folgenden Code gezeigt:
// 添加按钮绑定事件 this._elements.addButton.click(function(e){ that.addButtonClicked.notify(); });
Rufen Sie dann die Benachrichtigungsmethode in der Beobachterklasse Event auf (veröffentlichen Sie ein Ereignis). Wie wir alle wissen, wird der Beobachtermodus auch als Publish-Subscribe-Modus bezeichnet, sodass mehrere Beobachterobjekte ein Ereignis überwachen können bestimmtes Ereignis gleichzeitig. Wenn sich ein Themenobjekt ändert, werden alle davon abhängigen Objekte benachrichtigt
Daher können wir in der Kontrollschicht (Controller) den folgenden Code verwenden, um den Herausgeber zu überwachen:
this._view.addButtonClicked.attach(function(){ that.addItem(); });
addItem: function(){ var item = window.prompt('Add item:', ''); if (item) { this._model.addItem(item); } }
// 增加一项 addItem: function(elem) { this._elems.push(elem); this.itemAdd.notify({elem:elem}); },
// 绑定模型监听器 this._model.itemAdd.attach(function(){ that.rebuildList(); });
Die Modellschicht (Modell) ist hauptsächlich für die Kapselung von Geschäftsdaten verantwortlich. Die Ansichtsebene (Ansicht) veröffentlicht hauptsächlich Ereignisvorgänge und überwacht Daten auf der Modellebene. Wenn sich die Daten auf der Modellebene ändern, werden die Seitenvorgänge rechtzeitig aktualisiert und schließlich hauptsächlich auf der Seite angezeigt Überwacht die Ansichtsebene (Ansicht). Rufen Sie die Methode der Modellebene (Modell) auf, um die Daten auf der Modellebene zu aktualisieren. Schließlich wird die Ansichtsebene (Ansicht) veröffentlicht. Aktualisiert die Seite durch Überwachung der Datenänderungen der Modellebene (Modellanzeige). Das Obige ist der grundlegende Prozess von MVC.
Vorteile von MVC:
1. Geringe Kopplung: Die Ansichtsebene und die Geschäftsebene sind getrennt. Wenn sich die Anzeige auf der Seite ändert, kann sie direkt in der Ansichtsebene geändert werden, ohne das Modell zu berühren Ebene und Steuerung Der Code auf der Ebene; das heißt, die Ansichtsebene, die Modellebene und die Kontrollebene
Bereits getrennt; daher ist es einfach, die Datenschicht und die Geschäftsregeln der Anwendungsschicht zu ändern.
2. Wartbarkeit: Die Trennung der Ansichtsschicht und der Geschäftslogikschicht erleichtert auch die Wartung und Änderung von WEB-Anwendungen.
Nachteile von MVC:
Persönlich denke ich, dass es für große Projekte geeignet ist, aber nicht für kleine und mittlere Projekte, da für einfache Hinzufügungs-, Lösch- und Änderungsvorgänge nur wenig JS-Code, aber die Menge an MVC-Moduscode erforderlich ist ist deutlich gestiegen.
Natürlich steigen auch die Lernkosten, wenn Sie einige gekapselte MVC-Bibliotheken oder -Frameworks verwenden.
Das Obige ist eine detaillierte Analyse der MVC-Musterimplementierungsmethode in JavaScript sowie ihrer Vor- und Nachteile. Ich hoffe, dass sie für das Lernen aller hilfreich sein wird.