如何使用javascript的PureMVC框架 - Mediator/View层

本实例的最终源文件下载地址

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按钮看看吧!



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值