MVC模式是軟體工程中一種軟體架構模式,一般把軟體模式分成三個部分,模型(Model)+視圖(View)+控制器(Controller);
模型:模型用於封裝與應用程式的業務邏輯相關的資料以及對資料處理的方法。模型有對資料直接存取的權利。模型不依賴 “視圖” 和 “控制器”, 也就是說 模型它不關心頁面如何顯示及如何被操作.
視圖:視圖層最主要的是監聽模型層上的資料改變,並且即時的更新html頁。當然也包含一些事件的註冊或ajax請求操作(發布事件),都是放在視圖層來完成。
控制器:控制器接收使用者的操作,最主要是訂閱視圖層的事件,然後呼叫模型或視圖去完成使用者的操作;例如:當頁面上觸發一個事件,控制器不輸出任何東西及對頁面做任何處理; 它只是接收請求並決定調用模型中的那個方法去處理請求, 然後再確定調用那個視圖中的方法來顯示返回的數據。
下面我們來實作一個簡單的下拉框控件,我們可以對它進行增刪操作;如下圖:
程式碼如下:
/* 模型用于封装与应用程序的业务逻辑相关的数据以及对数据处理的方法。模型有对数据直接访问的权利。 模型不依赖 "视图" 和 "控制器", 也就是说 模型它不关心页面如何显示及如何被操作. */ 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); } };
HTML程式碼如下:
<select id="list" size="10" style="width: 10rem">select>br/> <button id="plusBtn"> + button> <button id="minusBtn"> - button>
頁面初始化程式碼如下:
$(function () { var model = new Mode(['PHP', 'JavaScript']), view = new View(model, { 'list' : $('#list'), 'addButton' : $('#plusBtn'), 'delButton' : $('#minusBtn') }), controller = new Controller(model, view); view.show(); });
程式碼分析如下:
先分析下我們要達到什麼樣的功能,基本功能有:
一個下拉框,透過使用者輸入的操作來實現使用者增加一項及使用者選取一項後刪除一項的功能;
當然也加入了用戶切換到那一項的事件;
例如我們現在來增加一條資料的時候,在視圖層上新增監聽事件,如下程式碼:
// 添加按钮绑定事件 this._elements.addButton.click(function(e){ that.addButtonClicked.notify(); });
然後呼叫觀察者類別Event中的方法notify(發布一個事件) that.addButtonClicked.notify();大家都知道,觀察者模式又叫發布-訂閱模式,讓多個觀察者對象同時監聽某一個主題對象,當某一個主題對象改變的時候,所有依賴它的對像都會被通知;
因此在控制層(Controller)我們可以使用以下程式碼對發布者進行監聽操作:
this._view.addButtonClicked.attach(function(){ that.addItem(); });
之後呼叫自身的方法addItem();程式碼如下:
addItem: function(){ var item = window.prompt('Add item:', ''); if (item) { this._model.addItem(item); } }
呼叫模型層(model)的方法addItem();把一條資料插入select框裡面去;model(模型層)的addItem()方法程式碼如下:
// 增加一项 addItem: function(elem) { this._elems.push(elem); this.itemAdd.notify({elem:elem}); },
如上程式碼 增加一項後,透過 this.itemAdd 發布一個訊息,然後在視圖層(View)上透過以下程式碼來監聽這個訊息;程式碼如下:
// 绑定模型监听器 this._model.itemAdd.attach(function(){ that.rebuildList(); });
最後監聽到模型上(Model)的資料改變後,及時呼叫自身的方法rebuildList()去更新頁面上的資料;
模型層(Model)最主要做業務資料封裝作業。視圖層(View)主要發布事件操作及監聽模型層上的數據,如果模型層上有數據改變的時候,及時更新頁面操作,最後顯示給頁面上來,控制層(Controller)主要監聽視圖層(View)的事件,呼叫模型層(Model)的方法來更新模型上的數據,模型層數據更新後,會發布一條訊息出去,最後視圖層(View)透過監聽模型層(Model)的數據變化,來更新頁面的顯示; 如上是MVC的基本流程。
MVC的優點:
1. 耦合性低:視圖層和業務層分離了,如果頁面上顯示改變的話,直接在視圖層更改即可,不用動模型層和控制層上的程式碼;也就是視圖層與模型層和控制層
已經分離了;所以很容易改變應用層的資料層和業務規則。
2. 可維護性:分離視圖層和商業邏輯層也使得WEB應用更容易維護和修改。
MVC的缺點:
個人覺得適合於大型項目,而中小型項目並不適合,因為要實現一個簡單的增刪改操作,只需要一點點JS代碼,但是MVC模式代碼量明顯增加了。
對於學習成本也就提高了,當然如果使用一些封裝好的MVC庫或框架就好了。
以上就是關於javascript中的MVC模式實作方法,優缺點的詳細分析,希望對大家的學習有所幫助。