Home  >  Article  >  Web Front-end  >  Talk about the MVC pattern in JavaScript_Basic knowledge

Talk about the MVC pattern in JavaScript_Basic knowledge

WBOY
WBOYOriginal
2016-05-16 17:37:43945browse

Original text: Model-View-Controller (MVC) with JavaScript
Author: Alex@Net
Translation: MVC pattern of JavaScript
Translator: justjavac

This article introduces the implementation of the model-view-controller pattern in JavaScript.

I love JavaScript because it is one of the most flexible languages ​​in the world. In JavaScript, programmers can choose the programming style according to their taste: procedural or object-oriented. If you are a heavy user, JavaScript can handle it with ease: process-oriented, object-oriented, aspect-oriented. Using JavaScript developers can even use functional programming techniques.

In this article, my goal is to write a simple JavaScript component to show everyone the power of JavaScript. This component is an editable list of items (select tag in HTML): the user can select an item and delete it, or add new items to the list. The component will be composed of three classes, corresponding to the model-view-controller of the MVC design pattern.

This article is just a simple guide. If you wish to use it in a real project, you will need to make appropriate modifications. I believe you have everything you need to create and run JavaScript programs: a brain, hands, a text editor (like Notepad), and a browser (like my favorite, Chrome).

Since our code will use 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, its main parts are:

•Model(), used to store data used in the program;
•View, used to present data in different forms;
•Controller (Controller), updated the model.
In Wikipedia’s definition of MVC architecture, it consists of the following three parts:

Model - "Data model" (Model) is used to encapsulate data related to the business logic of the application and how to process the data. The "model" has direct access to the data. The "model" does not depend on the "view" and "controller", that is, the model does not care how it will be displayed or how it will be manipulated.

View - The view layer enables the purposeful display of data, usually a user interface element. There is generally no procedural logic in views. In MVC in web applications, the html page that displays dynamic data is usually called a view.

Controller (Controller) - handles and responds to events, usually user operations, and monitors changes on the model, and then modifies the view.

The data of the component is a list of items, in which one particular 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 items in the list can be selected and deleted. Therefore, the component model is very simple - it only requires two properties:

1. The array _items is used to store all elements
2. The ordinary variable _selectedIndex is used to store the selected element index
The code is as follows:

Copy code The code is as follows:

/**
* Model.
*
* The model stores all elements and notifies the Observer when the state changes.
*/
function ListModel(items) {
    this._items = items;        // 所有元素
    this._selectedIndex = -1;   // 被选择元素的索引

    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.notify({item : item});
    },

    removeItemAt : function (index) {
        var item;

        item = this._items[index];
        this._items.splice(index, 1);
        this.itemRemoved.notify({item : item});

        if (index === this._selectedIndex) {
            this.setSelectedIndex(-1);
        }
    },

    getSelectedIndex : function () {
        return this._selectedIndex;
    },

    setSelectedIndex : function (index) {
        var previousIndex;

        previousIndex = this._selectedIndex;
        this._selectedIndex = index;
        this.selectedIndexChanged.notify({previous : previousIndex});
    }
};

Event 是一个简单的实现了观察者模式(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);
        }
    }
};

View 类需要定义控制器类,以便与它交互。 虽然这个任务可以有许多不同的接口(interface),但我更喜欢最简单的。 我希望我的项目是在一个 ListBox 控件和它下面的两个按钮:“加号”按钮添加项目,“减”删除所选项目。 组件所提供的“选择”功能则需要 select 控件的原生功能的支持。

一个 View 类被绑定在一个 Controller 类上, 其中「…控制器处理用户输入事件,通常是通过一个已注册的回调函数」(wikipedia.org)。

下面是 View 和 Controller 类:

复制代码 代码如下:

/**
* View.
*
* The view displays model data and triggers UI events.
* The controller is used to handle 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;

    // 绑定模型监听器
    this._model.itemAdded.attach(function () {
        _this.rebuildList();
    });

    this._model.itemRemoved.attach(function () {
        _this.rebuildList();
    });

    // 将监听器绑定到 HTML 控件上
    this._elements.list.change(function (e) {
        _this.listModified.notify({ index : e.target.selectedIndex });
    });

    this._elements.addButton.click(function () {
        _this.addButtonClicked.notify();
    });

    this._elements.delButton.click(function () {
        _this.delButtonClicked.notify();
    });
}

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($(''));
            }
        }

        this._model.setSelectedIndex(-1);
    }
};

/**
* Controller.
*
* The controller responds to user operations and calls the change function 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 = window.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);
    }
};

当然,Model, View, Controller 类应当被实例化。

下面是一个使用此 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();
});





 

 

 

 


 

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn