`
aniu2008
  • 浏览: 41745 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Flex学习笔记

    博客分类:
  • Flex
阅读更多

Flex学习笔记(-)安装- -
   废话少说,直奔主题,首先到Macromedia的网站上下载flex-15-win.exe和FlexBuilder1.5Installer.exe两个安装文件,第一个是Flex的服务器端程序,第二个是Flex文件(.mxml)编辑工具,根据提示一路next,注意如果你没有合法的许可证这两个软件只提供60天的试用。
  安装weblogic并配置一个domian,这个对于java程序员太简单了,不说了,这两步完成以后首先到flex的安装目录(C:\Program Files\Macromedia\Flex)下找到flex.war和samples.war两个war包,拷贝到别的目录,改名用RAR解压缩,在WEB-INF目录下下增加一个weblogic.xml文件,主要是增加这个东西:<context-root>/ria</context-root>,在weblogic下发布一下,OK。
  最后对这两个war包做一个说明,第一个是flex的基础运行环境,当你需要开发自己的Flex应用的时候只需要复制这个目录里的所有文件并根据自己的需要修改相应的配置文件就可以了。第二个是例程,使用"http://localhost:端口号/samples"这个地址访问。
Flex学习笔记(二)和J2EE进行交互 
  首先撰写mxml文件:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" verticalGap="20">
    <mx:HTTPService id="employeeSrv" method="get" url="employee.jsp" resultFormat="xml" result="getMessage()">
        <mx:request>
            <name>{name.text}</name>
            <email>{email.text}</email>
            <phone>{phone.text}</phone>
            <zipcode>{zipcode.text}</zipcode>
        </mx:request>
    </mx:HTTPService>
 
 <mx:Form>
 
  <mx:FormHeading label="增加员工"></mx:FormHeading>
  
        <mx:FormItem label="Name">
            <mx:TextInput id="name" width="200" />
        </mx:FormItem>
        <mx:FormItem label="Email">
            <mx:TextInput id="email" width="200" />
        </mx:FormItem>
        <mx:FormItem label="Phone">
            <mx:TextInput id="phone" width="200" />
        </mx:FormItem>
        <mx:FormItem label="ZipCode">
            <mx:TextInput id="zipcode" width="60" />
        </mx:FormItem>
        <mx:HBox width="100%" textAlign="center">
            <mx:Button label="Submit" click="employeeSrv.send();" />
            <mx:Button label="Reset" click="clearText();" />
        </mx:HBox>
    </mx:Form>
 
 <mx:Script>
  
  function getMessage()
  {
       var xmlNodes:Array = employeeSrv.result.childNodes;
       mx.controls.Alert.show( (xmlNodes[0].childNodes)[0].toString() , 'Message');
       clearText();
  }
  
  function clearText()
  {
       name.text = "";
       email.text = "";
       phone.text = "";
       zipcode.text = "";
  }
    </mx:Script>
 
</mx:Application>
然后是JSP文件:
<%@ page contentType="text/xml; charset=utf-8" %>
<%
request.setCharacterEncoding( "utf-8" );
System.out.println( request.getParameter( "name" ) );
System.out.println( request.getParameter( "phone" ) );
System.out.println( request.getParameter( "email" ) );
System.out.println( request.getParameter( "zipcode" ) );
%>
<root>
 <msg>Success!</msg>
</root>
注意红字的部分,在那里声明了一个HTTPService,当你点击Submit按钮的时候HTTPService就会把你填写的数据提交到后台的JSP页面,在JSP页面里就可以使用request.getParameter方法取出你填写的内容,JSP最后返回一个XML文档被mxml页面的getMessage()函数所处理,并在屏幕上显示出Success!
特别提示:HTTPService中的method属性在处理中文的时候请使用GET方式,POST方式会出乱码,这个问题很多朋友都遇到过,请注意。
Flex学习笔记(三)Flex发送XML数据中文乱码的解决
  上篇文章我提到过使用HTTPService向服务器传送数据如果含有中文字符要使用GET方式,否则会出乱码,经过测试中文乱码现象在使用HTTPService传送含有中文的XML内容的时候也存在。注意:这里说的是HTTPService向后台传送XML数据,不是后台向Flex客户端发送XML数据,后者只要使用UTF-8的编码是没有问题的。经过两天的试验最后问题终于解决。 
  第一步,在服务器端要有能够进行BASE64编码的java工具类,下载地址:
Encoder.java
Base64Encoder.java
Base64.java
怎么使用怎么修改我不说了,地球上会写java的都知道。
  第二步,撰写测试mxml文件,这里只展示关键代码。
<mx:HTTPService id="employeeSrv" contentType="application/xml" method="get" url="employee.jsp" resultFormat="xml" result="getMessage()" showBusyCursor="true"/>注意红字的地方不能少。
<mx:RemoteObject id="base64" source="com.zt.util.Base64" result="sendMessage( event.result )" fault="alert(event.fault.faultstring, 'Error')">
<mx:method name="encode"/>
</mx:RemoteObject>声明一个RemoteObject,并使用encode方法对还有中文的XML数据进行编码,结果存放在event.result对象中,并由sendMessage函数进行处理。
<mx:Button label="Submit" click="getContent();" />
function getContent()
{
var xml:XML = new XML();
var rootElement:XMLNode = xml.createElement( "root" );
var contentElement:XMLNode = xml.createElement( "name" );
var textElement:XMLNode = xml.createTextNode( name.text );
contentElement.appendChild( textElement );
rootElement.appendChild( contentElement );
contentElement = xml.createElement( "email" );
textElement = xml.createTextNode( email.text );
contentElement.appendChild( textElement );
rootElement.appendChild( contentElement );
xml.appendChild( rootElement );
base64.encode( xml.toString() );
}当Submit按钮的click事件被触发的时候打包XML数据,并进行BASE64的编码工作。
function sendMessage( obj )
{
var xml:XML = new XML();
var rootElement:XMLNode = xml.createElement( "root" );
var textElement:XMLNode = xml.createTextNode( obj.toString() );
rootElement.appendChild( textElement );
xml.appendChild( rootElement );
employeeSrv.send( xml );
}此函数obj参数就是进行了BASE64编码后的数据,进行二次打包发送到服务器。
  第三步,服务器端的处理,这里只是演示是否得到了正确的数据,所以没有业务逻辑,关键代码如下:
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build( request.getInputStream() );
System.out.println( Base64.decode( doc.getRootElement().getText() ) );
控制台上已经打印出了正确的含有中文的原始XML数据。
  注意事项:RemoteObject方法的执行和结果的返回是异步机制它不会等到执行结果返回就会执行后面的语句,所以以下的写法是错误的,服务器每次得到的是你上次发送的结果。
var resultObj = null;
function sendMessage()
{
    var xml:XML = new XML();
    var rootElement:XMLNode = xml.createElement( "root" );
    var contentElement:XMLNode = xml.createElement( "name" );
    var textElement:XMLNode = xml.createTextNode( name.text );
    contentElement.appendChild( textElement );
    rootElement.appendChild( contentElement );
    contentElement = xml.createElement( "email" );
    textElement = xml.createTextNode( email.text );
    contentElement.appendChild( textElement );
    rootElement.appendChild( contentElement );
    xml.appendChild( rootElement );
    base64.encode( xml.toString() );
    xml = new XML();
    rootElement = xml.createElement( "root" );
    textElement = xml.createTextNode( resultObj.toString() );
    rootElement.appendChild( textElement );
    xml.appendChild( rootElement );
    employeeSrv.send( xml );
}
Flex学习笔记(四)修改默认样式- -
  在Flex里Alert和ToolTip这类提示功能提供的默认样式的外观字体大小等显示英文字符是没有问题的,但是显示中文字符就显的字号偏小,文字几乎看不清楚,查阅了Flex的开发文档,发现这两个东西的样式是可以改变的。
  先说Alert,首先建立两个样式。
<mx:Style>
AlertTitle

font-size: 12pt; 
font-weight: bold;

AlertMessage
{
font-size: 12pt; 
}
<mx:Style/>
然后创建一个函数
import mx.controls.Alert;
function initAlert()
{
Alert.titleStyleDeclaration = "AlertTitle";
Alert.messageStyleDeclaration = "AlertMessage";
}
最后设置Application标签的initialize属性:initialize="initAlert()"
  再说ToolTip,这个东西我们在写Web应用的时候经常使用,例如:<mx:TextInput width="500" toolTip="请填写公司全称" />。我们要做的工作就是修改tooltip属性的默认字体大小等外观样式,这个更简单了,只要建立样式表即可。
ToolTip
{
font-size: 12pt;
}
  更多的样式设定请仔细阅读开发文档,另外这些样式如果是正式开发,最好写到CSS里,用Flex去引用CSS文件,做到外观的一致。
Flex学习笔记(五)日期控件的本地化和输入的格式化
  Flex里的日期输入控件默认月份的显示是英文的,偶的英文很一般,就知道那十二个单词代表月份,具体是哪个月,要数一下,最近的项目又是对公网用户服务,什么年龄段的都有,如果让50岁的人看英文,那结果我都不感想了。
  查阅了Flex的开发文档,发现修改控件的monthNames属性就能解决这个问题,这个属性是个数组,我们做一下的修改。首先在脚本里定义一个数组:var month:Array = new Array("1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月");然后我们可以这样使用控件:<mx:DateField width="180" monthNames="{month}" />,这样日期就变成了中文。
  日期数据的格式化和上面的做法类似,首先定义格式化函数:
 function formatDate(date:Date):String
 {
  return date.getUTCFullYear() + "-" + ( date.getUTCMonth() + 1 ) + "-" + ( date.getUTCDate() + 1 );
 }
日期控件我们就这样写:<mx:DateField width="180" dateFormatter="formatDate" />
  为了方便使用,可以把这个做成自定义组件。
Flex学习笔记(六)页面跳转- -
  Flex将mxml文件在服务器端编译成flash然后才发往客户端展示,所以我们不能像在JSP里一样使用response.sendRedirect()方法进行页面的跳转,今天仔细的看了一下Flex的例程,发现它的页面跳转简单异常。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml">
  <mx:Script>
  <![CDATA[
    var url:String = "employee.mxml.swf"
 function modifyURL()
 {
  url = "corporation.mxml.swf";
 }
  ]]>
  </mx:Script>
  <mx:VBox label="Sample" minWidth="0" minHeight="0" width="100%" height="100%" marginTop="8" marginLeft="8">
 <mx:Loader id="loader" contentPath="{url}" scaleContent="false" showBusyCursor="true"/>
  </mx:VBox>
  <mx:Button label="Button" click="modifyURL()" />
</mx:Application>
这就是我写的测试例程,三个文件:index.mxml,employee.mxml,corporation.mxml放在web应用的根目录下就可以了,上面的代码是index.mxml的代码。其余两个文件写什么就随便了,只要不是错的。 
对Flex学习笔记(六)的补充说明- -
   在Flex学习笔记(六)里我介绍了使用Loader组件动态加载Flex页面的方法,但是后来发现加载的页面只能在很小的一个范围内显示,无论怎么设定Loader的参数都没有效果,这个问题今天终于搞明白了,下面做一下说明。
  要想让动态加载进来的页面满屏显示,不但要设定container和Loader组件的长度和宽度的参数,还要设定加载进来的swf的长度和宽度的参数。加载进来的swf存放在Loader组件的content属性里面,当Loader组件加载完毕会触发它自己的complete事件,在该事件中我们调整一下swf的长宽参数即可,关键代码如下:
function initSwf()
{
    loader.content.width="2000";
    loader.content.height="2000";
}
<mx:Loader id="loader" width="100%" height="100%" contentPath="{url}" scaleContent="false" showBusyCursor="true" complete="initSwf()"/>
Flex学习笔记(七)动态生成组件- -
  今天看了一个RIA论坛上关于动态生成组件的一个话题,感觉挺重要的,有时候我们会根据业务的需要决定一个输入框等组件是否被创建,如果组件能被动态创建和撤销,那么页面的复用就成为可能了。那位老兄说,Flex的文档指出从UIComponent继承的对象才能绘图,直接在Application或Continer上绘图是没有效果的。这句话我感觉有问题,下面的代码是我从Flex开发文档里看到的,对大家动态创建、撤销组件会有帮助。
<?xml version="1.0"?> 
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" >
  <mx:Script>
  <![CDATA[
    // Import the Checkbox class.
    import mx.controls.CheckBox;
    // Define a variable to hold the new CheckBox control.
    var addedCheckBox:CheckBox;
    // Define a variable to track if you created a CheckBox control.
    var checkBoxCreated:Boolean = false;
    function addCB()
    { 
        // Test to see if you have already created the CheckBox control.
        if(checkBoxCreated==false)
        {
            addedCheckBox = CheckBox(myHB.createChild(CheckBox, undefined, {label:"New CheckBox",toolTip:"test"}));
            checkBoxCreated=true;   
        }
    }
    function delCB()
    {
        // Make sure a CheckBox control exists.
        if(checkBoxCreated==true)
        {   
            myHB.destroyChild(addedCheckBox); 
            checkBoxCreated=false;   
        }
    }
  ]]>
  </mx:Script>
  <mx:VBox >
    <mx:HBox id="myHB" borderStyle="solid" />
    <mx:Button label="add CheckBox" click="addCB()" />
    <mx:Button label="remove CheckBox" click="delCB()" />
  </mx:VBox> 
</mx:Application>
  红字部分是你对该控件的多个属性进行赋值的写法。
Flex学习笔记(八)List组件的使用- -
  这次我来说明一下List组件的使用,主要是当multipleSelection的属性设为"true"的时候的技巧。
  1.选择了多项条目后数据的读取,关键代码如下:
  function getSelectedItems()
  {
      var selectItems:Array = state.selectedItems;
      var iCount:Number = selectItems.length;
      var xml:XML = new XML();
      var rootElement:XMLNode = xml.createElement( "root" );
      for( var i:Number = 0 ; i < iCount ; i++ )
      {
         var contentElement:XMLNode = xml.createElement( "state" );
         var textElement:XMLNode = xml.createTextNode( selectItems[i].data );
         contentElement.appendChild( textElement );
         rootElement.appendChild( contentElement );
      }
      xml.appendChild( rootElement );
      mx.controls.Alert.show( xml.toString() , 'Message');
  }
  state是List组件的id,在List组件里如果允许多选,那么被选定的那些条目会被存放在组件的selectedItems属性里,该属性是Object一个数组,每个元素的data属性对应该条目的值,后面的代码就是为了把结果显示出来而已,不解释了。
  2.根据后台发来的数据决定选项是否是选定状态,关键代码如下:
  function initApp()
  {
      var selectedItems:Array = new Array();
      var iCount:Number = state.length;
      for( var i:Number = 0 ; i < iCount ; i++ )
      {
         if( state.getItemAt( i ).data == "AL" || state.getItemAt( i ).data == "AK" )
         {
            selectedItems.push( i );
         }
      }
      state.selectedIndices = selectedItems;
  }
  lenth属性保存了List组件里数据条目的总数,循环使用getItemAt()方法遍历所有条目(这里假设后台发来的数据如果值是"AL"或者"AK"则设定为选定状态),如果值相等,则将该条目在List组件里的索引号保存到一个数组里面,最后将这个类型为数组的临时变量的值赋给List组件的selectedIndices属性,操作完成。
Flex学习笔记(九)拖拽效果的实现- -
  废话不说,直奔主题,拿两个List组件放到页面上,是否允许多选随便,对List与拖拽相关的属性做如下设定:dragEnabled="true",dragEnter="doDragEnter(event)",dragExit="doDragExit(event)",dragDrop="doDragDrop(event)",dragOver="doDragOver(event)",dragComplete="doDragComplete(event)"。
  除了第一个属性,其余的一看大家就应该知道都是函数,这些函数的实现我放在DragEventHandlers.as文件里,该脚本可以使用<mx:Script source="DragEventHandlers.as" />引用,注意两个文件都在同一目录下才可以这么写。好了,在你的服务器上运行一下看看效果。
  处理拖拽事件的脚本是我从macromedia公司samples下目录下找到的,没有什么特殊需求应该可以作为通用方法使用。
Flex学习笔记(十)弹出窗口的实现以及子父窗口的数据交换- -
  Flex里使用PopUpManager.createPopUp(parent, class, modal [, initobj, outsideEvents])创建父一个子窗口,该函数的参数说明如下:
parent 一个引用,引用弹出窗口所在的窗口。 
class 一个引用,引用要创建的对象的类。
modal 一个布尔值,它表明该窗口是 (true) 否 (false) 是模式的。
initobj  一个包含初始化属性的对象。此参数是可选的。
outsideEvents  一个布尔值,指明在用户单击窗口以外的区域时是 (true) 否 (false) 触发事件。此参数是可选的。
其中,前三个参数是必须的,后两个是可选的。第二个参数要和你的mxml文件名一致,第三个参数如果选择是则不允许弹出窗口没关闭前操作父窗口,反之则允许。
  首先我们创建一个页面,关键代码如下:
<mx:Button label="Show Window" click="showWindow(false)" width="150"/>
<mx:Button label="Show Modal Window" click="showWindow(true)" width="150"/>
function showWindow(modal)
{
    var popup = mx.managers.PopUpManager.createPopUp(_root , login , modal, {deferred: true});
}
  然后我们创建一个TitleWindow,注意虽然也是mxml文件,但是它的定级元素不是Application而是TitleWindow,其余的地方和以前没什么两样了。
  下面介绍子父窗口的数据交换。
  当子窗口被创建的时候父窗口就获得了一个子窗口的实例,注意我用红子标出的变量。我们可以用该变量引用子窗口内定义的全局变量,例如我在子窗口中做如下定义:var name:String = "哈哈";。在父窗口中可以使用popup.name引用该变量。
  同样,在子窗口中我们可以使用"parent"来引用父窗口中定义的变量,例如我在父窗口中定义var age:String="24";。在子窗口中可以使用parent.age引用这个变量。
小结一下- -
  学习笔记不知不觉已经写了十篇了,说说自己这一段时间的学习体会,Flex的编程模型是以事件驱动的,所以如果你有VB或者PB之类编程语言的经验掌握起来就比较快。
  在动手写第一Flex应用的时候建议好好看一下MM公司的sample,不光是看它的效果,更要注意它的代码,并且在你以后使用过程当中也要记得经常翻看,里面很多代码都有复用价值,有的甚至一行代码都不用修改就可以使用。
  学习过程中不要心急实现自己心中的一些想法,先模仿着做,模仿熟练了再去创新,《Contributing to Eclipse》一书中曾经提到一个原则叫有样学样原则就是这样。
  Flex的开发文档虽然写的离JDK的开发文档还有很大的一段距离,但是依然很有参考价值,当然能看懂英语是前提,不过我这么烂的英语水平都能勉强看懂,大家就更没问题了。
  Flex组件的使用我建议大家看看Flash的帮助文档,这个东西可是有中文的,对你学习使用那些组件很有帮助。
  剩下的就是多多练习,多多实验,不要怕出错。现在多出错,将来项目少出错。
  下面的话写给向我提问的朋友,非常想给你们提供帮助,只要你们在这里留言或者发电子邮件我一定尽力解答,但是请你们提问的时候不要只说我什么什么东西用不了,要提供详细的错误信息、源代码、运行环境等,只有这样我才有可能知道你问题出在什么地方,才能给出正确的解答。
  最后唠叨两句,十分不喜欢ActionScript的语法风格,写起来不爽,更喜欢java或者C#的风格。
Flex学习笔记(十一)令人困惑的CheckBox- -
  这两天在研究Flex里的CheckBox,发现它和HTML下的CheckBox不太一样,在HTML里面使用CheckBox三个属性比较重要,CheckBox的名字、值、文字解释,但是在Flex里CheckBox没有值这个属性,感觉这个地方设计的似乎有问题。
  在Flex里感觉CheckBox应该和RadioButton的定义类似才对。不知道当时MM公司是怎么想的,变通的解决办法就是使用List组件代替CheckBox。
乱弹RIA- -
                                       
  学习Flex也有半个多月了,说说我对RIA各种技术实现的看法。
  未来Flex和微软的XAML肯定会是RIA技术的主流,就跨平台的能力看非Flex莫数,就功能方面则是微软略胜一筹。javascript+xmlhttp和J2SE+WebStart很难和前面两种技术媲美,javascript存在着严重的浏览器兼容问题,J2SE则在开发周期和成本方面无法和XAML相比。
  Flex由于安全性上的原因(几乎不能读写本地文件,执行本机上的应用程序)未来可能会更多的应用到面对公网服务的Web应用上,而XAML由于对本地资源的操作性上可能会在企业、政府内部信息系统、综合业务系统上大显身手。
Flex学习笔记(十二)页面间的数据共享- -
  在前面的学习笔记中我提到了利用Loader组件达到刷新局部页面的效果,接着就有网友问我该怎么在页面间传递参数,今天的学习笔记就来解决这个问题。
  在Flex里提供了一个SharedObject的类来提供用户计算机上永久对象间的实时数据共享。您可以将本地共享对象看作“Cookie”,但是SharedObject类只在本页面有效,也就是说当你页面跳转以后你是无法拿到上一个页面SharedObject存储的数据的,这个和Cookie不同,Cookie是可以跨页面共享数据的。
  虽然Flex不可以像使用JSP、ASP那样方便的传递参数,但是解决的办法不是没有。可以利用应用服务器的Session来解决这个问题。
  当你需要页面跳转的时候可以先把当前页面的参数使用HTTPService或者RemoteObject保存到应用服务器上,当下个页面需要数据的时候再从服务器上要,这个其实和JSP的原理是一样的,JSP使用name=value的方式传递参数,但是JSP的所有运算都在服务器上,Flex可是一个纯客户端环境,除了和服务器必要的数据交换,其他时候都是可以脱机运行的。
Flex学习笔记(十三)创建和使用自定义组件- -
  本次的学习笔记以本地话的DateInput组件为例说明如何创建和使用自定义组件。
  首先做个简单的说明,自定义组件要包含在容器中,容器只能是Canvas、HBox、Panel、VBox四种容器中,换句话说你定义组件的mxml文件的顶级XML元素必须是这四个的其中一个。如果在你的自定义组件里需要额外的属性设定,那么在自定义组件里的Script标签里根据需要定义变量即可,例如:var dateInputLength;,那么我们在使用组件的时候就可以用dateInputLength=""来设定这个属性。好,让我们开始。
  建立一个文件起名MyDate.mxml,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.macromedia.com/2003/mxml">
  <mx:Script>
  <![CDATA[
  var month:Array = new Array("1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月");
  function formatDate(date:Date):String
  {
    return date.getFullYear() + "-" + ( date.getMonth() + 1 ) + "-" + date.getDate();
  }
  ]]>
  </mx:Script>
  <mx:DateField monthNames="{month}" dateFormatter="formatDate" width="{width}" />
</mx:VBox>
由于这里我不需要使用任何额外的属性,所以不需要定义其他的变量,自定义组件就做好了。
  我们来使用它,使用它的页面和原来没什么太大的区别,只需要注意几个地方即可。
<mx:Application width="100%" xmlns:mx="http://www.macromedia.com/2003/mxml" xmlns="*">注意红字部分,这是和以前不一样的地方。
<MyDate width="180"/>这样就可以使用刚才我们定义的组件了。注意,元素开头没有mx:,另外元素的名字必须和文件名称一样。
面向对象(组件)的Flex- -
  在RIA论坛上的Flex专区转转发现网友问的问题基本可以分为两大类,一类是例如如何动态加载页面,如何和动态加载的页面进行数据交换之类的问题;另一类是如何翻转图片,如何设定字间距之类的问题。
  对于第二类问题我想再次声明,Flex应该看起来是Flash的简化版,只不过针对Web Application开发进行了加强,所以不要期望Flash可以解决的问题它也理所当然的能解决。你不妨问一下你自己这些问题在你开发Web Application时真的那么重要吗(请注意Web Application和Web Site词意上的不同)?没有别的替代方案吗?
下面我针对第一类问题进行深入的说明。以前,我们在做Web Application的UI设计的时候基本是以页面为单位的,页面包含着各种元素,例如:输入框,下拉列表,图片等等。Flex的出现不但给我们带来了全新的用户体验,而且给UI设计带来了全新的概念:对象、组件。
  当我们在为如何和动态加载的页面进行数据交换而头疼的时候不妨不思考一下为什么非要是一个页面而不可以是一个组件?传递数据的时候为什么不可以学习java把这些数据集合起来封装成bean再进行传递?
  ActionScript2.0和1.0相比主要针对OOD、OOP进行了加强,例如:interface、public、private、class、extends、implements等关键字的引入。这些关键字都是面向对象语言专有的,既然ActionScript2.0是OO语言那么Design Patterns当然也可以运用其中啊(在Essential ActionScript2.0一书中有专门的章节讲述如何将Design Patterns运用到ActionScript2.0的编程中)。
  我个人认为使用Flex的时候应该考虑的三大要素是:页面、组件、对象。页面,决定了整个应用的风格、布局等视觉因素。组件,可能是对某一特定业务的数据展示、用户交互等等功能的封装,可以在应用运行过程当中根据特定的条件(例如:用户权限、用户的某种操作等)动态的创建和撤销,组件由对象甚至其他的组件组合而成。对象我就不说了,因为讲述它的文章或者书籍多的不能再多了。
  最后,我用我自己使用Flex的感受结束本篇blog。要像使用OO语言一样的使用Flex。
DataGrid使用方式的探讨- -
  在话题开始前先说明一下,严格来说这个话题应该算UI设计方面的问题,但是由于我是和Flex的DataGrid为例来进行探讨,所以就放在了RIA的栏目。
  DataGrid控件提供了可以直接在控件上直接进行编辑的功能,但是我觉得这个功能的使用一定要慎重的考虑,是否使用这个功能和用户使用习惯一致性问题息息相关。所谓用户使用习惯一致性就是说对于同一个软件的同一个控件的使用方式最好是统一的。如果同一控件出现了两种不同的使用方式就会给用户带来困扰。
  我现在所在的项目组使用javascript也提供了类似的功能给开发人员使用。但在使用上就存在的两种截然不同的方式。当列表数据项较少的情况下大部分人选择了在控件上直接编辑数据,当数据项较多的时候则另外提供编辑界面。
  使用“可编辑”功能的好处就在于可以批量的增加、修改数据,可以给用户在使用上带来一些方便,可是如果“可编辑”和“不可编辑”两种方式的DataGrid同时出现在同一个软件里可能给用户带来的困扰我感觉要远大于它的便利性。
  我对使用这个功能的看法是:要么都用,要么都不用。
Flex学习笔记(十四)动态加载自定义组件- -
  上一次的学习笔记里我提到了如何创建基于mxml文件的自定义组件(还有一种方式是使用ActionScript直接编程的方式),并说明了如何在应用里如何使用标签的方式来使用组件,但是有时候我们需要根据应用的上下文环境决定一个组件是否被加载。下面就做一下说明。
  基于mxml文件的自定义组件你可以把它看成一个没有Package的ActionScript类,使用脚本语言动态加载自定义组件的方法和动态加载Flex提供的组件的方法是一样的,下面是示例代码(基于上次的MyDate组件)。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application initialize="initApp()" width="100%" xmlns:mx="http://www.macromedia.com/2003/mxml" xmlns="*">
  <mx:Script>
  <![CDATA[
  import mx.controls.Alert;
  function initApp()
  {
    var date:MyDate = MyDate( myHB.createChild( MyDate, undefined , {width:180} ) );
  }
  ]]>
  </mx:Script>
  <mx:HBox id="myHB" borderStyle="solid" width="100%" height="100%" />
</mx:Application>
Flex学习笔记(十五)弄明白了Menu组件里check类型Item的使用- -
  Menu组件里提供了check类型的MenuItem,和CheckBox组件类似,该类型的MenuItem有两种状态,在使用的时候选中状态下要执行一个动作,非选定状态下会执行一个相反的动作。但怎么得到这个MenuItem究竟是什么状态Macromedia提供的samples里面并没有示例代码,翻看了API文档找到了解决办法。
  在Menu类里面有一个静态方法isItemSelected( itm: Object) :  Boolean,它可以判断当前check类型的MenuItem是否选中(没找到这个东西之前虽然也实现了,但是方法太笨,这里就不公开了),下面分两种情况展示实现代码:
1.显示加载Menu组件:
function menuHandler(event)
{
  var isSelected:Boolean = true;
  if( event.menuItem.attributes.type == "check" )
  {
    isSelected = Menu.isItemSelected( event.menuItem );
  }
  if( isSelected )
  {
    mx.controls.Alert.show( "label: " + event.menuItem.attributes.label + " data: " + event.menuItem.attributes.data , "Message" );
  }
}
在Menu标签里的chang事件里声明一下即可,change="menuHandler(event)"
2.动态加载Menu组件(我们在菜单初始化的时候为期增加chang事件的监听器即可):
var menu:Menu;
function initMenu()
{
  menu = Menu.createMenu( null , menuData );
  
  var menuEventHandler = new Object();
  menuEventHandler.change = function( event )
  {
    var isSelected:Boolean = true;
    if( event.menuItem.attributes.type == "check" )
    {
      isSelected = Menu.isItemSelected( event.menuItem );
    }
    if( isSelected )
    {
      mx.controls.Alert.show( "label: " + event.menuItem.attributes.label + " data: " + event.menuItem.attributes.data , "Message" );
    }
  }
  var menuEventDelegate = mx.utils.Delegate.create( this , menuEventHandler.change );
  menu.addEventListener( "change" , menuEventDelegate );
}
Flex学习笔记(十六)编程控制Tree组件添加、删除节点
  看到很多RIA论坛上有人问怎么通过编程来增加或者删除Tree组件的节点,今天动手解决了这个问题。
  API文档里讲的很明白,Tree组件里有一个dataProvider的属性,该属性的类型是一个Object,但是它具有TreeDataProvider或者XMLTreeDataProvider的所有属性和方法,要实现添加或者删除节点就必须通过操作该对象来实现。下面展示关键代码。
1.Tree组件的描述看起来是这样的:
<mx:Tree id="testTree" height="100%">
  <mx:dataProvider>
    <mx:XML>
      <node label="index1" isBranch="true" />
      <node label="index2" isBranch="true">
        <node label="index5" />
        <node label="index6" />
      </node>
      <node label="index3" isBranch="true" />
      <node label="index4" isBranch="true" />
    </mx:XML>
  </mx:dataProvider>
</mx:Tree>
  我现在要在触发一个按钮的click事件时为第一个节点添加一个子节点,并为这个刚添加的节点增加一个子节点。
2.控制代码:
function addTreeNode()
{
  var provider = testTree.dataProvider;
  var treeNodes:Array = provider.getChildNodes();//返回第一层节点的数组
  treeNodes[0].addTreeNode( "test1" , null );
  ( treeNodes[0].getChildNodes() )[0].addTreeNode( "test2" , null );
}
  点击一下树的第一个节点,应该看见刚才增加的节点,删除节点的操作和增加节点一样,只不过使用的Method不一样而已。
Flex学习笔记(十七)列表类组件使用小技巧- -
  Flex里我们常用的列表组件有两个(List和ComboBox),最近在使用它们的时候发现了一些小技巧,并记录在这里。
  使用这两个组件的时候一般我们使用dataPovider为组件填充数据(数据源在这里假设是XML),默认情况下必须有一列的名字为label,其实这不是必须的,两个组件都有一个labelField属性,只要将该属性和数据源上的某列的名字绑定,那么该列就会作为label显示在组件里。
  在中文环境下,往往两个组件的label里填充的中文,当选项比较多的时候就会给用户快速选择带来麻烦,用户要一项一项的仔细查找。这时候我们可以为每个选项的中文前面添加一个英文或者数字代码来帮助用户进行快速定位。假设我有这样的数据结构:<country label="中国" data="CN"/>,这是一个国家选项,一般情况下要在那么多国家选项里快速找到某个国家不容易,但是如果我们将国家代码加到中文的开头,用户可以使用"C"键快速定位到所有国家代码以"C"字母开头的国家。
  要实现这个功能非常简单,首先我们要定义一个格式化函数,它看起来应该是这样:
function formatListItem( item:Object ):String
{
  return item.data + "  " + item.label;
}
然后设定组件的labelFunction属性,我们这样写:labelFunction="formatListItem",OK,就是这样。
Flex学习笔记(十八)开发和使用自定义验证类
  Flex在mx.validators包里提供了一些用于数据验证的类,例如:数字验证、日期验证、电子邮件验证等。但这对于开发中文环境下的应用程序来说是不够的,例如要验证身份证号码、中国的邮政编码等,这时候就需要我们开发自己的数据验证类。
  所有的数据验证类都必须继承mx.validators.Validator,并实现自己的doValidation( str:String ):Void方法,下面是示例代码:
class com.zt.validators.PostcodeValidator extends mx.validators.Validator
{
  public function doValidation( postCode:String ):Void
  {
    PostcodeValidator.validatePostcode( this , postCode , null );
  }
  
  public static function validatePostcode( validator:mx.validators.Validator , postCode:String , subField ):Boolean
  {
    var size = postCode.length;
    var test = postCode.toLowerCase();
    
    if( size != 6 )
    {
      validator.validationError( "wrongLength" , "邮政编码错误!" , subField );
      return false;
    }
    return true;
  }
}
该类需要放到WEB-INF/flex/user_classes/com/zt/validators目录下。在应用中我们可以这样使用它:<zt:PostcodeValidator field="" xmlns:zt="com.zt.validators.PostcodeValidator" />

  关于验证的时机,如果是单页的数据填报,那么在用户点击提交按钮的时候执行验证,如果是使用Accordion组件的多页数据填报,那么最好在换页时进行验证,如果验证失败,则不允许换页。
Flex的使用感受- -
  Flex也试用了一段时间了,感觉比较成熟了,用它开发一些简单的应用没有什么大问题,但是问题也不是没有。
  感觉问题最大的就是那个日期输入控件,如果你输入的日期和当天的日期要差很多年的时候就比较麻烦,要按N次左或者右的箭头。
  图表组件和表格组件如果能提供导出到PDF文件就更好了,另外表格组件最好能直接提供分页功能。
  控件类型还不够,页面布局方面也没在DW里编辑HTML那么方便。
  文档还不够详细,尤其是涉及到组件风格方面的,例如toolTip,alert这些东西,最好是有一份文档专门详细介绍页面风格各项属性的意义的就好了。
Flex学习笔记(十九)根据用户交互状态选择合适的验证方式
  对一个数据项的验证方法可能会根据用户当前操作不同而不同,比如:身份证号码验证(如果是中国公民则对应的是身份证号码的验证逻辑,否则可能是护照号码的验证逻辑)。Flex可以通过编程的方式,根据用户操作的结果动态选择合适验证方法。
  关键代码如下:
function updateCountry()
{
  Validator.isValid( this , "registration.postCode" );
}
function validateZipCodeField( validator , value )
{
  if( country.selectedItem.data == "AK" )
  {
    PostcodeValidator.validatePostcode( validator , value );
  }
  else
  {
    ZipCodeValidator.validateZipCode( validator , value );
  }
}
<mx:Model id="statesModel" source="states.xml"/>
<mx:ComboBox id="country" dataProvider="{statesModel.state}" change="updateCountry()"/>
<mx:TextInput id="postCode"/>
<mx:Validator field="registration.postCode" validate="validateZipCodeField( event.validator , event.value )"/>
第一个函数用来响应一个下拉列表框的change事件,第二个函数是具体的验证逻辑。这样就可以根据用户在ComboBox里选择的不同来确定针对postCode输入项合适的验证逻辑。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics