
代码如下:
/* 模型用于封装与应用程序的业务逻辑相关的数据以及对数据处理的方法。模型有对数据直接访问的权利。 模型不依赖 "视图" 和 "控制器", 也就是说 模型它不关心页面如何显示及如何被操作.*/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();大家都知道,观察者模式又叫发布-订阅模式,让多个观察者对象同时监听某一个主题对象,当某一个主题对象发生改变的时候,所有依赖它的对象都会得到通知;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()去更新页面上的数据;