Original article: Model-View-Controller (MVC) with JavaScript
Author: Alex @ Net
Translation: JavaScript MVC pattern
Translator: justjavac
This article introduces the implementation of Model-View-controller mode in JavaScript.
I like JavaScript because it is one of the most flexible languages in the world. In JavaScript, programmers can choose a programming style based on their own tastes: process-oriented or object-oriented. If you have a strong taste, JavaScript can be used as well: process-oriented, object-oriented, and Aspect-Oriented. JavaScript developers can even use functional programming technology.
In this article, my goal is to write a simple JavaScript component to show you how powerful JavaScript is. This component is an editable Project List (select tag in HTML). You can select an item and delete it, or add a new project to the list. The component is composed of three classes, which correspond to the Model-View-controller in the MVC design mode.
This article is just a simple guide. If you want to use it in the actual project, you need to make appropriate changes. I believe that you have everything you need to create and run JavaScript programs: brains, hands, text editors (such as NotePad), browsers (such as my favorite Chrome ).
Since our code uses the MVC pattern, I will briefly introduce this design pattern here. The English name of the MVC pattern is Model-View-Controller pattern. As the name suggests, it consists of the following parts:
- Model (), used to store the data used in the program;
- Views are presented in different forms;
- Controller to update the model.
In Wikipedia's definition of the MVC Architecture, it consists of the following three parts:
Model-Model is used to encapsulate data related to the application's business logic and to process the data. The "model" has the right to directly access data. "Model" does not depend on "View" and "controller", that is, the model does not care about how it is displayed or operated.
View-the View layer can display data purposefully. It is usually a user interface element. Generally, there is no program logic in the view. In Web applications, MVC usually calls the html page that displays dynamic data as a view.
Controller-handles and responds to events, usually user operations, monitors changes in the model, and then modifies the view.
The data of the component is a list of items, in which one particle item can be selected and deleted. so, the model of the component is very simple-it is stored in an array property and selected item property; and here it is:
We will implement a data list component based on MVC, and projects in the list can be selected and deleted. Therefore, the component model is very simple-It only requires two attributes:
- Array
_itemsUsed to store all elements
- Common variables
_selectedIndexUsed to store selected element Indexes
The Code is as follows:
/*** Model. ** The model stores all elements and notifies the Observer (Observer) when the status changes ). */Function ListModel (items) {this. _ items = items; // all elements this. _ selectedIndex =-1; // index of the selected element this. itemAdded = new Event (this); this. itemRemoved = new Event (this); this. selectedIndexChanged = new Event (this);} ListModel. prototype = {getItems: function () {return []. concat (this. _ items) ;}, addItem: function (item) {this. _ items. push (item); this. itemAdded. policy ({item: item}) ;}, removeItemAt: function (index) {var item; item = this. _ items [index]; this. _ items. splice (index, 1); this. itemRemoved. using Y ({item: item}); if (index = this. _ selectedIndex) {this. setSelectedIndex (-1) ;}}, getSelectedIndex: function () {return this. _ selectedIndex;}, setSelectedIndex: function (index) {var previusindex; previusindex = this. _ selectedIndex; this. _ selectedIndex = index; this. selectedIndexChanged. Y ({previous: previusindex });}};
EventIs a simple class that implements the Observer pattern:
function Event(sender) { this._sender = sender; this._listeners = [];}Event.prototype = { attach : function (listener) { this._listeners.push(listener); }, notify : function (args) { var index; for (index = 0; index < this._listeners.length; index += 1) { this._listeners[index](this._sender, args); } }};
ViewClass needs to define the Controller class to interact with it. Although this task can have many different interfaces, I prefer the simplest one. I want my project to add a project in a ListBox control and two buttons Under it: the plus sign button, and the minus sign to delete the selected project. The "select" function provided by the component is requiredselectSupports native functions of controls.
OneViewThe class is bound toControllerClass, where 「... The controller processes user input events, usually through a registered callback function (wikipedia.org ).
Below isViewAndControllerClass:
/*** View. ** The View displays model data and triggers UI events. * The controller is used to process these User Interaction Events */function ListView (model, elements) {this. _ model = model; this. _ elements = elements; this. listModified = new Event (this); this. addButtonClicked = new Event (this); this. delButtonClicked = new Event (this); var _ this = this; // bind the model listener this. _ model. itemAdded. attach (function () {_ this. rebuildList () ;}); this. _ model. itemRemoved. attach (function () {_ this. rebuildList () ;}); // binds the listener Set this to the HTML control. _ elements. list. change (function (e) {_ this. listModified. using Y ({index: e.tar get. selectedIndex}) ;}); this. _ elements. addButton. click (function () {_ this. addButtonClicked. Y () ;}); this. _ elements. delButton. click (function () {_ this. delButtonClicked. Y () ;});} ListView. prototype = {show: function () {this. rebuildList () ;}, rebuildList: function () {var list, items, key; List = this. _ elements. list; list.html (''); items = this. _ model. getItems (); for (key in items) {if (items. hasOwnProperty (key) {list. append ($ ('<option>' + items [key] + '</option>');} this. _ model. setSelectedIndex (-1) ;}};/*** controller. ** The Controller responds to user operations and calls variable functions on the model. */Function ListController (model, view) {this. _ model = model; this. _ view = view; var _ this = this; this. _ view. listModified. attach (function (sender, args) {_ this. updateSelected (args. index) ;}); this. _ view. addButtonClicked. attach (function () {_ this. addItem () ;}); this. _ view. delButtonClicked. attach (function () {_ this. delItem () ;}) ;} ListController. prototype = {addItem: function () {var item = w Indow. prompt ('add item: ', ''); if (item) {this. _ model. addItem (item) ;}}, delItem: function () {var index; index = this. _ model. getSelectedIndex (); if (index! =-1) {this. _ model. removeItemAt (this. _ model. getSelectedIndex () ;}}, updateSelected: function (index) {this. _ model. setSelectedIndex (index );}};
Of course,Model,View,ControllerClass should be instantiated.
The following is a complete code using this MVC:
$(function () { var model = new ListModel(['PHP', 'JavaScript']), view = new ListView(model, { 'list' : $('#list'), 'addButton' : $('#plusBtn'), 'delButton' : $('#minusBtn') }), controller = new ListController(model, view); view.show();});<select id="list" size="10" style="width: 15em"></select><br/><button id="plusBtn"> + </button><button id="minusBtn"> - </button>Original --------- reprint original address:
JavaScript MVC Mode