JavaScriptのMVCモード

6828 ワード

JavaScriptでのモデル-ビュー-コントローラモードの実装について説明します.
私はJavaScriptが好きです.世界で最も柔軟な言語の一つだからです.JavaScriptでは、プログラマーは自分の好みに合わせてプログラミングスタイルを選択できます.プロシージャ向けまたはオブジェクト向けです.もしあなたが重い味であれば、JavaScriptは同じように自由に対応することができます:プロセス向け、オブジェクト向け、側面向け、JavaScript開発者を使用して関数式プログラミング技術を使用することもできます.
この文章では、JavaScriptの強さを示す簡単なJavaScriptコンポーネントを作成することを目標としています.このコンポーネントは編集可能なアイテムリスト(HTMLのselectラベル):ユーザーはアイテムを選択して削除したり、新しいアイテムをリストに追加したりすることができます.コンポーネントは,MVC設計モードのモデル−ビュー−コントローラにそれぞれ対応する3つのクラスで構成される.
この文章はただ簡単な指導にすぎない.実際のプロジェクトで使用したい場合は、適切な修正が必要です.私はあなたがJavaScriptプログラムを作成し、実行するすべてを持っていると信じています.脳、両手、テキストエディタ(メモ帳など)、ブラウザ(私の大好きなChromeなど).
私たちのコードはMVCモードを使用する以上、ここで簡単にこの設計モードを紹介します.MVCモードの英語名はModel-View-Controller patternで、その名の通り、その主要な部分から構成されています.
  • モデルModel()は、プログラムで使用されるデータを格納するために使用される.
  • ビュー(View)は、異なる表現形式でデータを表示する.
  • コントローラ(Controller)、モデルを更新します.

  • ウィキペディアのMVCアーキテクチャの定義では、次の3つの部分から構成されています.
    「モデル」(Model)-「データ・モデル」(Model)は、アプリケーションのビジネス・ロジックに関連するデータおよびデータの処理方法をカプセル化するために使用されます.モデルには、データに直接アクセスする権限があります.モデルはビューとコントローラに依存しません.つまり、モデルがどのように表示されるか、またはどのように操作されるかには関心がありません.
    ビュー(View)-ビューレイヤは、通常、ユーザインタフェース要素であるデータの目的のある表示を実現することができる.ビューには一般的にプログラム上の論理はありません.WebアプリケーションにおけるMVCは、通常、動的データを表示するhtmlページをビューと呼ぶ.
    コントローラ(Controller)-通常、ユーザー操作であるイベントを処理および応答し、モデルの変化を監視してビューを変更します.
    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:
    MVCに基づいてデータリストコンポーネントを実装し,リスト内の項目を選択して削除することができる.したがって、コンポーネントモデルは非常に簡単です.2つのプロパティしか必要ありません.
  • 配列_itemsは、すべての要素
  • を格納するために使用される.
  • 通常変数_selectedIndexは、選択する要素インデックス
  • を格納するために使用される.
    /**
     *   。
     *
     *         ,            (Observer)。
     */ 
    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)がありますが、私は最も簡単なのが好きです.私は私のプロジェクトが1つのListBoxコントロールとその下の2つのボタンであることを望んでいます:“プラス記号”ボタンはプロジェクトを追加して、“マイナス”は選択したプロジェクトを削除します.コンポーネントが提供する「選択」機能には、selectコントロールのオリジナル機能のサポートが必要です.Viewクラスは、Controllerクラスにバインドされ、「コントローラは、通常、登録されたコールバック関数を介してユーザ入力イベントを処理する」(wikipedia.org).
    次はViewControllerのクラスです.
    /**
     *   。
     * 
     *         ,    UI   。
     *                
     */ 
    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($('<option>' + items[key] + '</option>'));
                }
            }
    
            this._model.setSelectedIndex(-1);
        }
    };
    
    /**
     *    。
     *
     *          ,          。
     */ 
    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);
        }
    };

    もちろん、ModelViewController類は実例化されるべきである.
    以下は、この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>