本实例的最终源文件下载地址
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";
使用this.sendNotification( NotificationNames.USER_LISTS_ADD_ITEM, user ); 发出来的消息可以在Mediator 里监听也可一在Command里监听,下面我写再写一个Mediator来监听由 UserFormMediator发出来的 NotificationNames.USER_LISTS_ADD_ITEM消息。
在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按钮看看吧!