本实例的最终源文件下载地址
http://download.csdn.net/detail/laogong5i0/4400288
继续前两次的
如何使用javascript的PureMVC框架 - 初始化
如何使用javascript的PureMVC框架 - Command/controller层
后,我们接下来要学习的是View层,Mediator的使用。
在上次如何使用javascript的PureMVC框架 - Command/controller层时我们曾使用Notification来触发Command的执行,其实Notification在PureMVC随处可以,它不仅可以用来触发Command的执行,在Mediator也是随处可见的!
在Mediator里,你可以发送、接收、声明notification,当Mediator被注册时,Mediator的listNotifications()方法会被调用,以数组形式返回该Mediator对象所关心的所有Notification。之后,当PureMVC其它角色发出同名的Notification(通知)时,关心这个通知的Mediator都会调用handleNotification()方法并将Notification以参数传递到方法。
理论上就说这么多,接下来是上代码!
首先在上两次教程里的html文件里添加一个div标签,内容为
<div align="center"> <form id="userForm"> <label>First Name</label> <input id="firstNmae" type="iniput" required /> <label>Last Name</label> <input id="lastNmae" type="iniput" required /> <input id="submit" type="button" value="Submit" /> </form> </div>然后在demo文件夹下新建view文件夹,并在view文件夹下新建components文件夹
跟着在components文件夹下新建UiComponent.js以及UserForm.js文件
UiComponent.js文件是一个用于程序的UI组件的基类,它主要添加一个基于UiComponent的实现,让UI组件从Mediators监听
UserForm.js是继承自UiComponent.js类的UI组件,主要是实现对form表单的引用及操作。
UiComponent.js文件内容为
/** * @class * 一个用于程序的UI组件的基类 * 它主要添加一个基于UiComponent的实现,让UI组件从Mediators监听 * 实现者和监听者是负责匿名事件对象的发送和接受 */ var UiComponent = Objs("demo.view.components.UiComponent", { /** * @construct * 初始化一个UiComponent实例 */ initialize: function() { this.listenerMap = {}; }, /** * 一个UiComponent.listenerDescriptor的映射对象 * @type {Object} * @private */ listenerMap: null, /** * 发送事件到事件流 * @param {String} type * 发送的事件类型 * @param {Object} properties * 可选的匿名对象,当dispatch时会被发送到事件监听器 */ dispatchEvent: function( type, properties ) { if( typeof type == 'undefined' ) return; if( typeof this.listenerMap[UiComponent.QUEUE_PATTERN + type] == 'undefined' ) return; var queue/*Array*/ = this.listenerMap[UiComponent.QUEUE_PATTERN + type].slice(0); var props/*Object*/ = properties || {}; var len/*Number*/ = queue.length; for(var i/*Number*/=0; i<len; i++) { var listenerDescriptor/*UiComponent.ListenerDescriptor*/ = queue[i]; if( typeof listenerDescriptor.listener == 'function' ) { if( typeof listenerDescriptor.context != "undefined" ) listenerDescriptor.listener.call( listenerDescriptor.context, props ); else listenerDescriptor.listener.call( this, event, props ); } } }, /** * 添加一个监听器去监听接收事件通知 * @param {String} type * 添加的事件类型 * @param {Function} listener * 添加事件监听器方法 * @param {Object} context * 添加事件监听方法的附加内容 */ addEventListener: function ( type, listener, context ) { if( typeof type == "undefined" ) return; if( typeof listener == "undefined" ) return; var newListener/*UiComponent.ListenerDescriptor*/ = new UiComponent.ListenerDescriptor( listener, context ); var queue/*Object*/; if( typeof this.listenerMap[ UiComponent.QUEUE_PATTERN + type ] == "undefined" ) queue = this.listenerMap[ UiComponent.QUEUE_PATTERN + type ] = []; else queue = this.listenerMap[ UiComponent.QUEUE_PATTERN + type ]; var len/*Number*/ = queue.length; for(var i/*Number*/=0; i<len; i++ ) { var listenerDescriptor/*UiComponent.ListenerDescriptor*/ = queue[i]; if( listenerDescriptor.equals( newListener ) ) return; } queue.push(newListener); }, /** * 删除一个事件监听器以便监听器停止接受notification事件 * @param {String} type * 删除的事件类型 * @param {Function} listener * 删除的事件监听器方法 * @param {Object} context * 删除事件监听方法的附加内容 */ removeEventListener: function ( type, listener, context ) { if( typeof type == "undefined" ) return; if( typeof listener == "undefined" ) return; if( typeof this.listenerMap[UiComponent.QUEUE_PATTERN + type] == "undefined" ) return; var queue/*Object*/ = this.listenerMap[ UiComponent.QUEUE_PATTERN + type ]; var len/*Number*/ = queue.length; for(var i/*Number*/=0; i<len; i++) { var listenerDescriptor/*UiComponent.ListenerDescriptor*/ = queue[i]; if( listenerDescriptor.equals( new UiComponent.ListenerDescriptor( listener, context ) ) ) { queue.splice(i,1); return; } } } }); /** * @class * @private * Event对象由UiComponent类派发到它的事件监听器 */ UiComponent.Event = Objs("demo.view.components.UiComponent.Event", { /** * 事件类型 * @type {String} */ type: null, /** * 随着dispatche event一起发送的属性 * @type {Object} */ properties: null }); /** * @private * 使用UiComoponent.listenerMap描述符对象鉴定各个事件监听器 * 这是Javascript的内部类 */ UiComponent.ListenerDescriptor = Objs("demo.view.components.UiComponent.Event", { /** * @construct * 初始化实例 * @param {Function} listener * 被调用的方法 * @param {Function} listener * 被调用方法的内容 */ initialize: function( listener, context ) { this.listener = listener; this.context = context; }, /** * @private * 对比两UiComponent.ListenerDescriptor 以确定与目标相同的事件监听器。 * * @param {UiComponent.ListenerDescriptor} compared * descriptor将与当前的内容做对比 * @return {Boolean} * 两个对比监听的的boolean值 */ equals: function( compared ) { if( compared.listener == this.listener ) { if( typeof compared.context != "undefined" ) { if( compared.context == null && this.context == null ) return true; if( compared.context == this.context ) return true; } } return false; } }); //一个字符前缀,用于防止项目名冲突 UiComponent.QUEUE_PATTERN = '@_@';
在编写UserForm.js前我们先在demo文件夹下新建一个model文件夹,然后在model文件夹下新建一个vo文件夹来存放user对象类,吧user信息写成一个对象类,方便以后使用,以及程序看起来跟清晰。
在vo文件夹下新建User.js文件夹,内容为
var UserVO = Objs("demo.model.vo.UserVO", { firstName: "", lastName: "", /* * 判断用户是否合法 */ getIsValid: function() { return this.firstName != "" && this.lastName != "" ; } });
接下是UserForm.js内容
var UserForm = Objs("demo.view.components.UserForm", UiComponent, { user: null, sweepsFields: null, firstName: null, lastName: null, submit: null, /** * @construct * @override * 初始化UserForm实例. */ initialize: function() { //调用父类中的initialize函数 UserForm.$super.initialize.call( this ); this.initializeChildren(); this.configureListeners(); this.clearForm(); this.setEnabled(false); }, /** * 初始化对html元素的引用 */ initializeChildren: function() { this.sweepsFields = $("#userForm"); this.firstName = this.sweepsFields.find("#firstNmae"); this.lastName = this.sweepsFields.find("#lastNmae"); this.submit = this.sweepsFields.find("#submit").button(); }, /** * 注册监听事件 */ configureListeners: function() { var that = this; this.submit.click( function(evt){ that.submit_clickHandler(evt) } ); }, /** * 设置一个user用来填充表单 * @param {UserVO} user */ setUser: function( user ) { this.user = user; if( !user ) this.clearForm(); else { this.firstName.val(user.firstName); this.lastName.val(user.lastName); } }, /** * 获取用户 */ getUser: function()/*UserVO*/ { this.updateUser(); return this.user; }, /** * 根据fields的值更新用户属性 */ updateUser: function() { this.user = new UserVO(); this.user.firstName = this.firstName.val(); this.user.lastName = this.lastName.val(); }, /** * 清除整个表单 */ clearForm: function() { this.firstName.val(""); this.lastName.val(""); }, /** * 时用或者禁用form表单 * @param {Boolean} isEnabled */ setEnabled: function( isEnabled ) { if( isEnabled ) { this.firstName.removeAttr("disabled"); this.lastName.removeAttr("disabled"); } else { this.firstName.attr( "disabled", "disabled" ); this.lastName.attr( "disabled", "disabled" ); } }, /** * 按下submit时调用 */ submit_clickHandler: function() { this.updateUser(); //判断user信息是否合法,如果不合法提示并返回 if( !this.user.getIsValid() ) { alert('Please typing you First Name and Last Name'); return; } // 调用基类UiComponent的dispatchEvent方法,派发UserForm.ADD事件 this.dispatchEvent( UserForm.ADD ); }, }); /* * Event names */ UserForm.ADD/*String*/ = "add";
接下来就是在Mediator里面操作UserForm实例了!
在view文件夹下新建UserFormMediator.js文件内容如下,主要功能是按Submit按钮后发送this.sendNotification( NotificationNames.USER_LISTS_ADD_ITEM, user );命了
var UserFormMediator = Objs("demo.view.UserFormMediator", Mediator, { /** * @construct * @override * 初始化UserFormMediator实例 * @param {String} name * Mediator的名称 * @param {UserForm} viewComponent * Mediator所管理的UserForm视图组件 */ initialize: function( name, viewComponent ) { UserFormMediator.$super.initialize.call( this, name, viewComponent ); var userForm = this.getUserForm(); //注册监听事件userForm.ADD,当触发时会调用onAdd方法,即监听submit按钮是否按下 userForm.addEventListener( UserForm.ADD, this.onAdd, this ); var user = new UserVO(); user.firstName='pat'; user.lastName='chen'; userForm.setUser(user); }, /** * @private * 获取UserFrom视图组件 */ getUserForm : function() { return this.viewComponent; }, /** * @private * 当用户按submit时调用 * @param {UiComponent.Event} event * The dispatched event object. */ onAdd: function( event ) { var user = this.getUserForm().getUser(); //使用PureMVC发送notification消息 //在这里你需要在上次如何使用javascript的PureMVC框架 - Command/controller层提到的NotificationNames.js文件里添加 //NotificationNames.USER_LISTS_ADD_ITEM = "user_lists_add_item";内容 this.sendNotification( NotificationNames.USER_LISTS_ADD_ITEM, user ); var userForm = this.getUserForm(); userForm.clearForm(); userForm.setEnabled(true); }, /** * @override * 注册时被调用 */ onRegister: function() { }, /** * @override * 当本Mediator被移除是被调用 */ onRemove: function() { }, /** * 把要监听的事件添加到这个数组里去, * 当this.facade.sendNotification( notice, data);时,就会调用handleNotification();方法 * @override */ listNotificationInterests: function() { return [ ]; }, /** * 在这里处理使用 this.facade.sendNotification( notice, data);发出来的事件 * @override */ handleNotification: function( note ) { var userForm = this.getUserForm(); var user; switch ( note.getName() ) { } } }); /* * Constants */ UserFormMediator.ADD/*String*/ = "add";
在view文件夹下新建UserListsMediator.js文件,内容如下
var UserListsMediator = Objs("sweeps.view.UserListsMediator", Mediator, { /** * @construct * @override * 初始化UserListsMediator实例 * @param {String} name * Mediator的名称 * @param {UserlistsForm} viewComponent * Mediator所管理的UserlistsForm视图组件 */ initialize: function( name, viewComponent ) { UserFormMediator.$super.initialize.call( this, name, viewComponent ); }, /** * 把要监听的事件添加到这个数组里去, * 当this.facade.sendNotification( notice, data);时,就会调用handleNotification();方法 * @override */ listNotificationInterests: function() { return [ NotificationNames.USER_LISTS_ADD_ITEM ]; }, /** * 在这里处理使用 this.facade.sendNotification( notice, data);发出来的事件 * @override */ handleNotification: function( note ) { var data = note.getBody(); switch ( note.getName() ) { case NotificationNames.USER_LISTS_ADD_ITEM: alert('firs name: ' + data.firstName + " \nlast name: " + data.lastName); break; } } });
到这里我们还需要吧写好的Mediator注册到PureMVC中,
在上次如何使用javascript的PureMVC框架 - Command/controller层所提到的PrepViewCommand类里面知道到 execute方法,修改 execute()方法
execute: function( note ) { //初始化View对象 var userForm = new UserForm(); //初始化Mediator对象 var userFormMediator = new UserFormMediator( 'USER_FORM_MEDIATOR', userForm ); var userListsMediator = new UserListsMediator( 'USER_LISTS_MEDIATOR',null); //注册Mediators this.facade.registerMediator( userFormMediator ); this.facade.registerMediator( userListsMediator ); }
最后所有文件的目录树为
那么所有类都写好了!就是剩下吧所有使用到的类导入到html里面了;
<script type="text/javascript" src="src/demo/model/vo/UserVO.js"></script> <script type="text/javascript" src="src/demo/view/UserFormMediator.js"></script> <script type="text/javascript" src="src/demo/view/UserListsMediator.js"></script> <script type="text/javascript" src="src/demo/view/components/UiComponent.js"></script> <script type="text/javascript" src="src/demo/view/components/UserForm.js"></script> <script type="text/javascript" src="src/demo/abc/NotificationNames.js"></script> <script type="text/javascript" src="src/demo/controller/PrepViewCommand.js"></script> <script type="text/javascript" src="src/demo/controller/StartupCommand.js"></script> <script type="text/javascript" src="src/demo/ApplicationFacade.js"></script>
这里的类文件比较多,这就是面向对象的特色啦,文件比较多,但当你熟悉后你就不觉得了,反而维护起来很方便。
如果你觉得太多,怕影响浏览速度的话,你只要在发布的时候吧这些文都压缩到一个文件里去就行了,我这里没有压缩,所有看起来比较麻烦。
按一下submit按钮看看吧!