ExtJS4终于出了正式版,体验一下面官方推荐的向对象编程最佳实践

过去的做法是new对象或者Ext.create一个对象,每个对象都要先实例化才能使用

ExtJS4推荐定义类的时候均使用Ext.define,利用xtype动态加载

修改了以前的一个登陆窗口,感觉用官方推荐的方法还是很不错的

但还有一些问题没有想得非常清楚,先把代码贴出来一起研究下。请看代码中的注释~~

使用Ext+.Net,用Direct模式传递数据

Default.aspx:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
  <title>ExtJS学习</title>
  <link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css" />
  <link rel="stylesheet" type="text/css" href="css/application.css" />
  <script src="ext/ext-all.js" type="text/javascript"></script>
  <script src="ext/ext-lang-zh_CN.js" type="text/javascript"></script>
  <script type="text/javascript" src="ChcekLogin.ashx"></script>
  <script src="js/Ext.app.LoginFormPanel.js" type="text/javascript"></script>
  <script type="text/javascript" src="js/Ext.app.LoginDialog.js"></script>
</head>
<body>
  <div id="loading-mask"></div>
  <div id="loading">
    <div class="loading-indicator"><img alt="" src="ext/resources/themes/images/default/shared/large-loading.gif" width="32" height="32" style="margin-right:8px;" align="absmiddle"/>正在加载...</div>
  </div>
  <script type="text/javascript">
      //Ext.Loader.setConfig({ enabled: true });
      Ext.onReady(function () {
          Ext.BLANK_IMAGE_URL = 'img/s.gif';
          Ext.QuickTips.init();
          Ext.Msg.minWidth = 300;
          //验证提示信息显示位置
          Ext.form.Field.prototype.msgTarget = 'side';
          //如果是继承Ext.container.Viewport的实例,直接new出来就可以,会自动渲染到body
          //本例中Ext.app.LoginDialog继承自Ext.Window,需要调用show()方法才能显示
          new Ext.app.LoginDialog().show();
          //250毫秒后删除加载提示信息
          setTimeout(function () {
              Ext.get('loading').remove();
              Ext.get('loading-mask').fadeOut({ remove: true });
          }, 250);

      })//onReady

  </script>
</body>
</html>

Ext.app.LoginDialog.js

//LoginDialog类,继承Ext.Window,上层对象使用new Ext.app.LoginDialog().show()动态实例化并显示。
Ext.define('Ext.app.LoginDialog',{
	extend:'Ext.Window',
	title: '登陆',
      plain: true,
      closable: false,
      closeAction: 'hide',
      width: 400,
      height: 300,
      layout: 'fit',
      border: false,
      modal: true,
      //使用xtype: 'LoginFormPanel'动态实例化Ext.app.LoginFormPanel,并使用api参数指定load和submit的服务器端方法。本例中只有submit
      items: {itemId: 'loginFormPanel',xtype: 'LoginFormPanel',api: {submit: MyApp.ChcekLogin.Check}}
});

Ext.app.LoginFormPanel.js

//指定远程调用的Provider,注意不能在initComponent中指定,因为config属性设置是在initComponent之前,会报api找不到错误
Ext.direct.Manager.addProvider(Ext.app.REMOTING_API);

//loginForm类,继承Ext.form.FormPanel,使用alias注册至ComponentMgr,上层对象使用xtype:LoginFormPanel动态实例化。
//form的submit()方法使用Direct提交,上层对象实例化本类的时候使用config中的api属性指定服务器端方法。
//很奇怪的是不能在Ext.define或者Ext.apply中指定api属性,指定了实例化之后也会丢失,然后报url参数没有的错误,只能在上层对象实例化本类得时候使用config中的api属性指定api
//如果在这里使用原始的new方法指定api也可以,是ext4中的问题?有谁知道的发mail告诉我,万分感谢~~
//使用Ext.define定义本类,定义中使用initComponent指定实例化之前需要执行的操作。
//按面向对象编程思想,本类不调用任何上层对象,方法中不指定scope: this
Ext.define('Ext.app.LoginFormPanel',{
	
		extend:'Ext.form.FormPanel',
		initComponent: function(){
			//初始化部分需要完成的功能
			//alert("Ext.form.FormPanel 开始加载……");
			//貌似Ext.apply得来的属性和在Ext.define中定义的没什么区别,为什么要用这个呢?谁来教教我?
			Ext.apply(this, {
				//labelAlign: 'left'
				});
			this.callParent();
			},
		alias:'widget.LoginFormPanel',
		labelAlign: 'left', 
		buttonAlign: 'center',
		bodyStyle: 'padding:5px', 
		frame: true, labelWidth: 80,
		
		items: [
	    	  { xtype: 'textfield', name: 'txt1', fieldLabel: '用户名称',
	    	      allowBlank: false, anchor: '90%', enableKeyEvents: true,
	    	      listeners: {
	    	          keypress: function (field, e) {
	    	              if (e.getKey() == 13) {
	    	              	this.nextSibling().focus();
	    	              }
	    	          } //keypress
	    	      }
	    	  },
	    	  { xtype: 'textfield', inputType: 'password', name: 'txt2', fieldLabel: '用户密码',
	    	      allowBlank: false, anchor: '90%', enableKeyEvents: true,
	    	      listeners: {
	    	          keypress: function (field, e) {
	    	              if (e.getKey() == 13) {
	    	              	this.nextSibling().focus();
	    	              }
	    	          } //keypress
	    	      }
	    	  },
 				  { xtype: 'textfield', name: 'txt3', fieldLabel: '验证码',
 				      allowBlank: false, anchor: '90%', mixLength: 6, maxLength: 6, enableKeyEvents: true,
 				      listeners: {
 				          keypress: function (field, e) {
 				              if (e.getKey() == 13) {
 				                  this.ownerCt.submit();
 				              }
 				          } //keypress
 				      }
 				  },
 				  { xtype: 'panel', height: 100, html: '<div style="margin:5px 0px 0px 84px"><a href="#"><img alt="如果看不清楚请单击图片更换图片。" onclick="this.src=\'vcode.ashx?d=\'+new Date();" id="code" height="82" width="242" src="vcode.ashx" border="0"></a></div>', border: false },
 				  { xtype: 'panel', height: 30, html: '<div style="margin:5px 0px 0px 84px;color:red">*如果图片不清晰请单击图片更换图片</div>', border: false }
			  ], //items
                buttons: [
		    	{ text: '确定', handler: function () { this.findParentByType('LoginFormPanel').submit(); }},
		    	//面向本对象编程,这里不要加入 scope: this,否则function会指定到window上面
	      	{ text: '重置', handler: function () { this.findParentByType('LoginFormPanel').form.reset(); } }
	      ],
	      submit: function () {
            if (this.getForm().isValid()) {
                this.getForm().submit({
                    success: function (form, action) {
                    		window.location = "main.htm";
                    },
                    failure: function (form, action) {
                    		//使用form参数访问原submit的form
                        form.reset();
                        //使用action.result访问结果集
                        Ext.MessageBox.alert('登陆失败', action.result.data);
                    }
                })
            }
		    		}
});

过程已经写到注释里面了,有什么问题请在下面讨论

作者: vic.lu 发表于 2011-05-12 18:20 原文链接

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架