《Flex4权威指南》一次小总结,前11课

http://url.cn/MhcbAc 礼包码:5lbckopvl4n  ,这个地址是《Flex4权威指南》中的全部代码的下载地址,分享一下共同学习。

因为我暂时只能这样分享了,资源在我的115网盘里,可能还得需要注册吧。

一、VO包   

1.值对象Product.as

package valueObjects {
	[Bindable]
	public class Product {
		public var catID:Number;
		public var prodName:String;
		public var unitID:Number;
		public var cost:Number;
		public var listPrice:Number;
		public var description:String;
		public var isOrganic:Boolean;
		public var isLowFat:Boolean;
		public var imageName:String;

		public function Product( catID:Number, prodName:String, unitID:Number,
								 cost:Number, listPrice:Number, description:String, isOrganic:Boolean,
								 isLowFat:Boolean, imageName:String ) { 
			this.catID = catID;
			this.prodName = prodName;
			this.unitID = unitID;
			this.cost = cost;
			this.listPrice = listPrice;
			this.description = description;
			this.isOrganic = isOrganic;
			this.isLowFat = isLowFat;
			this.imageName = imageName;
		}

		public function toString():String {
			return "[Product]" + this.prodName;
		}

		public static function buildProduct( o:Object ):Product {
			var p:Product;
			
			p = new Product( o.catID, o.prodName, o.unitID, o.cost,
							 o.listPrice, o.description, ( o.isOrganic == 'true' ),
							 ( o.isLowFat == 'true' ), o.imageName );
			
			return p;
		}
		
		public static function buildProductFromAttributes( data:XML ):Product {
			var p:Product;
			var isOrganic:Boolean = ( data.@isOrganic == "Yes" );
			var isLowFat:Boolean = ( data.@isLowFat == "Yes" );

			p = new Product( data.@catID,
				data.@prodName,
				data.@unitID,
				data.@cost,
				data.@listPrice,
				data.@description,
				isOrganic,
				isLowFat,
				data.@imageName );
			return p;
		}
	}
}


二、services包

1.CategoryService.as

package services {
	import mx.collections.XMLListCollection;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.mxml.HTTPService;
	
	public class CategoryService extends HTTPService {
		[Bindable]
		public var categories:XMLListCollection;
		
		public function CategoryService(rootURL:String=null, destination:String=null) {
			super(rootURL, destination);

			this.resultFormat = "e4x";
			this.url = "http://localhost:8080/toFlex/category.xml";

			addEventListener(ResultEvent.RESULT, handleCategoryResult);
		}
		
		private function handleCategoryResult(event:ResultEvent):void{
			categories = new XMLListCollection( event.result.category );
		}		
	}
}

2.ProductService.as

package services {
	import mx.collections.ArrayCollection;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.mxml.HTTPService;
	
	import valueObjects.Product;
	
	public class ProductService extends HTTPService {
		[Bindable]
		public var products:ArrayCollection;
		
		private var selectedCategory:Number=1;

		public function ProductService(rootURL:String=null, destination:String=null) {
			super(rootURL, destination);

			this.resultFormat="e4x";
			this.url="http://localhost:8080/toFlex/categorizedProducts.xml";
			
			addEventListener(ResultEvent.RESULT, handleProductResult);
		}
		
		private function handleProductResult( event:ResultEvent ):void {
			var productsArray:Array = new Array();
			var resultData:XMLList = event.result..product;
			for each (var p:XML in resultData) {			
				var product:Product = Product.buildProductFromAttributes( p );
				productsArray.push( product );
			}

			products = new ArrayCollection( productsArray );
			products.filterFunction = filterForCategory;
			products.refresh();
		}	
		
		public function filterForCategory( item:Product ):Boolean{
			return item.catID == selectedCategory;
		}	
		
		public function filterCollection( id:Number ):void{
			selectedCategory = id;
			products.refresh();
		}		
	}
}

三、主页或叫主应用程序(FlexGrocery.mxml)包括controlbarContent和ShoppingView组件

FlexGrocery.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx"
			   xmlns:views="views.*" xmlns:services="services.*"
			   creationComplete="handleCreationComplete(event)">

	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
		<services:CategoryService id="categoryService"/>
		<services:ProductService id="productService"/>
	</fx:Declarations>

	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;
			
			import spark.events.IndexChangeEvent;
			
			private function handleViewCartClick( event:MouseEvent ):void {
				bodyGroup.currentState="cartView";
			}

			private function handleCreationComplete(event:FlexEvent):void {
				categoryService.send();
				productService.send();
			}
			


			protected function list1_changeHandler(event:IndexChangeEvent):void
			{
				productService.filterCollection( event.target.selectedItem.categoryID );
			}

		]]>
	</fx:Script>

	<s:controlBarLayout>
		<s:BasicLayout/>
	</s:controlBarLayout>
	
	<s:controlBarContent>
		<s:Button y="10" label="Checkout" id="btnCheckout" right="10"/>
		<s:Button y="10" label="View Cart" id="btnCartView" right="90" click="handleViewCartClick( event )"/>
		<s:Button label="Flex Grocer" x="5" y="5"/>
		<s:List left="200" height="52" 
				dataProvider="{categoryService.categories}" 
				itemRenderer="components.NavigationItem"
				change="list1_changeHandler(event)">
			<s:layout>
				<s:HorizontalLayout/>
			</s:layout>
		</s:List>
	</s:controlBarContent>
	<s:Label text="(c) 2009, FlexGrocer" right="10" bottom="10"/>
	<views:ShoppingView id="bodyGroup" 
						width="100%" height="100%"
						groceryInventory="{productService.products}"/>

</s:Application>

controlBarContent使用呈现器为:NavigationItem组件


NavigationItem.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
				xmlns:s="library://ns.adobe.com/flex/spark" 
				xmlns:mx="library://ns.adobe.com/flex/mx">
	<s:layout>
		<s:VerticalLayout horizontalAlign="center"/>
	</s:layout>
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
	<mx:Image
		source="assets/nav_{data.name.toLowerCase()}.jpg"
		height="31" width="93"/>
	<s:Label text="{data.name}"/>
</s:ItemRenderer>


ShoppingView包括:ProductList,视图状态state1和cartVIew,及cartView视图的内容

ShoppingView.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
		 xmlns:s="library://ns.adobe.com/flex/spark" 
		 xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:components="components.*">
	<s:layout>
		<s:HorizontalLayout/>
	</s:layout>
	<fx:Script>
		<![CDATA[
			import cart.ShoppingCart;
			import cart.ShoppingCartItem;
			
			import events.ProductEvent;
			
			import mx.collections.ArrayCollection;
			
			import valueObjects.Product;

			[Bindable]
			public var shoppingCart:ShoppingCart = new ShoppingCart();			
			
			[Bindable]
			public var groceryInventory:ArrayCollection;

			private function handleViewCartClick( event:MouseEvent ):void {
				this.currentState="cartView";
			}			

			private function renderProductName( item:ShoppingCartItem ):String {
				var product:Product = item.product;
				return '(' + item.quantity + ') ' + product.prodName + ' $' + item.subtotal;
			}
			
			private function addProductHandler( event:ProductEvent ):void {
				var sci:ShoppingCartItem = new ShoppingCartItem( event.product );
				shoppingCart.addItem( sci );
			}

			private function removeProductHandler( event:ProductEvent ):void {
				var sci:ShoppingCartItem = new ShoppingCartItem( event.product );
				shoppingCart.removeItem( sci );
			}
			
		]]>
	</fx:Script>	
	<s:states>
		<s:State name="State1"/>
		<s:State name="cartView"/>
	</s:states>	
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>

	<components:ProductList width="100%" height="100%"
							width.cartView="0" height.cartView="0"
							visible.cartView="false"
							dataProvider="{groceryInventory}"
							addProduct="addProductHandler( event )"
							removeProduct="removeProductHandler( event )"/>

	<s:VGroup height="100%" id="cartGroup" width.cartView="100%">
		<s:List id="cartList"
				dataProvider="{shoppingCart.items}"
				includeIn="State1"
				labelFunction="renderProductName"/>			
		<s:Label text="Your Cart Total: ${shoppingCart.total}"/>
		<s:Button label="View Cart" click="handleViewCartClick( event )" includeIn="State1"/>
		<mx:DataGrid includeIn="cartView" id="dgCart" width="100%">
			<mx:columns>
				<mx:DataGridColumn headerText="Column 1" dataField="col1"/>
				<mx:DataGridColumn headerText="Column 2" dataField="col2"/>
				<mx:DataGridColumn headerText="Column 3" dataField="col3"/>
			</mx:columns>
		</mx:DataGrid>
		<s:Button includeIn="cartView" label="Continue Shopping" click="this.currentState=''"/>
	</s:VGroup>

</s:Group>

四、cart包(包名如果改为services包可能会更容易理解,因为这个包里是业务逻辑对象,但是services包给了远程数据获取类了,在这里直接命名包名为所提供的功能未尝不可)

1.ShoppingCartItem.as    跟踪操作的商品,含商品对象、商品数量及小计金额,当数量发生改变时更改小计金额

package cart {
	import valueObjects.Product;

	[Bindable]
	public class ShoppingCartItem {
		public var product:Product;
		private var _quantity:uint;
		public var subtotal:Number;

		public function ShoppingCartItem( product:Product, quantity:uint=1 ){
			this.product = product;
			this.quantity = quantity;
			calculateSubtotal();
		}
		
		public function get quantity():uint
		{
			return _quantity;
		}

		public function set quantity(value:uint):void
		{
			_quantity = value;
			calculateSubtotal();
		}

		private function calculateSubtotal():void{
			this.subtotal = product.listPrice * quantity;
		}
		
		public function toString():String {
			return "[ShoppingCartItem] " + product.prodName + ":" + quantity;
		}
	}
}

2.ShoppingCart.as   业务逻辑大部分在这里

package cart {
	import mx.collections.ArrayCollection;
	import mx.collections.IViewCursor;
	import mx.collections.Sort;
	import mx.collections.SortField;
	import mx.events.CollectionEvent;

	public class ShoppingCart {
		[Bindable]
		public var items:ArrayCollection = new ArrayCollection();

		[Bindable]
		public var total:Number = 0;

		public function ShoppingCart() {//在构造器中使用ArrayCollection的排序功能
			var prodSort:Sort = new Sort();
			var sortField:SortField = new SortField( "product" );
			prodSort.fields = [ sortField ];
			items.sort = prodSort;
			items.refresh();
			items.addEventListener(CollectionEvent.COLLECTION_CHANGE, handleItemsChanged );//集合中的某一项发生变化,调用handleItemsChanged方法
		}

		public function addItem( item:ShoppingCartItem ):void {
			if ( isItemInCart( item ) ) {
				updateItem( item );
			} else {
				items.addItem( item );
			}
		}

		public function removeItem( item:ShoppingCartItem ):void {
			var cursor:IViewCursor = items.createCursor();//使用光标删除ArrayCollection数据,集合一定要事先排好序

			if ( cursor.findFirst( item ) ) {
				cursor.remove();
			}
		}

		private function getItemInCart( item:ShoppingCartItem ):ShoppingCartItem {
			var existingItem:ShoppingCartItem;
			var cursor:IViewCursor = items.createCursor();//用光标查找ArrayCollection数据,集合一定要事先排好序

			var found:Boolean = cursor.findFirst( item );

			if ( found ){
				existingItem = cursor.current as ShoppingCartItem;
			}

			return existingItem;
		}

		private function isItemInCart( item:ShoppingCartItem ):Boolean {
			var sci:ShoppingCartItem = getItemInCart( item );

			return ( sci != null );
		}

		private function updateItem( item:ShoppingCartItem ):void {
			var existingItem:ShoppingCartItem = getItemInCart( item );
			existingItem.quantity += item.quantity;
		}
//还能指定ArrayCollection的filterFunction实现集合的过滤功能,此处没有使用此功能
		private function calculateTotal():void{
			var newTotal:Number = 0;
			var existingItem:ShoppingCartItem;

			for ( var i:uint=0; i<items.length; i++ ) {
				existingItem = items[ i ] as ShoppingCartItem;
				newTotal += existingItem.subtotal;
			}
			
			this.total = newTotal;
		}

		public function toString():String {
			return "[ShoppingCart $" + total + "] " + items;
		}
		
		private function handleItemsChanged( event:CollectionEvent ):void {
			calculateTotal();
		}
	}
}

五、events包,继承Event类,定制自己需要的事件对象

ProductEvent.as  自定义Event,增加属性使其能添加自己想添加的信息

package events {
	import flash.events.Event;
	
	import valueObjects.Product;
	
	public class ProductEvent extends Event {
		public var product:Product;

		public function ProductEvent(type:String, product:Product ) {
			super(type, true);
			this.product = product;
		}
		
		public override function clone():Event{
			return new ProductEvent(type, product);
		}
	}
}

六、components包(组件包),只要一谈到让组件的工作更具体化,就意味着要创建一个组件的子类。如将ShoppingView组件再细分为,{展示商品:[展示商品所用的数据集:ProductList.mxml,数据集使用的呈现器:ProductItem.mxml]},上面提到的ShoppingView、NavigationItem.mxml组件也是在components包中

ProductList.mxml   数据集,呈现器为ProductItem(并没有在呈现器中指定dataProvider而是在呈现器的父容器的父容器ShoppingView.mxml中指定dataProvider,上级容器指定能够达到松解耦合的目的)

<?xml version="1.0" encoding="utf-8"?>
<s:DataGroup xmlns:fx="http://ns.adobe.com/mxml/2009" 
			 xmlns:s="library://ns.adobe.com/flex/spark" 
			 xmlns:mx="library://ns.adobe.com/flex/mx"
			 itemRenderer="components.ProductItem">
	<s:layout>
		<s:VerticalLayout/>
	</s:layout>
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
	<fx:Metadata>
		[Event(name="addProduct",type="events.ProductEvent")]
		[Event(name="removeProduct",type="events.ProductEvent")]
	</fx:Metadata>	
</s:DataGroup>


ProductItem.mxml 为直接继承的DataRenderer的呈现器,DataRenderer实现了IDataRenderer接口,ProductItem就不必再实现IDataRenderer接口了。 包含视图状态expanded(商品详细信息),元数据事件(表示该对象能派发的事件),使用VGroup展示商品(名字,图片,价格,加入购物车,从购物车删除的操作)

<?xml version="1.0" encoding="utf-8"?>
<s:DataRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
		 xmlns:s="library://ns.adobe.com/flex/spark" 
		 xmlns:mx="library://ns.adobe.com/flex/mx"
		 width="100%">
	<fx:Metadata><!--<fx:Metadata>元数据标签,表示该对象会分派addProduct和removeProduct事件,类型同为events.ProductEvent-->
		[Event(name="addProduct",type="events.ProductEvent")]
		[Event(name="removeProduct",type="events.ProductEvent")]
	</fx:Metadata>	
	<s:layout>
		<s:HorizontalLayout/>
	</s:layout>
	<s:states>
		<s:State name="State1"/>
		<s:State name="expanded"/>
	</s:states>		
	<fx:Script>
		<![CDATA[
			
			import events.ProductEvent;
			
			import valueObjects.Product;

			[Bindable]
			public var product:Product;

			private function addToCart( product:Product ):void {
				var event:ProductEvent = new ProductEvent( "addProduct", product );
				dispatchEvent( event );
			}
			
			private function removeFromCart( product:Product ):void {
				var event:ProductEvent = new ProductEvent( "removeProduct", product );
				dispatchEvent( event );
			}
			
			public override function set data(value:Object):void{//itemRenderer的原理就是针对dataProvider中的每一个数据项都创建一个呈现器的实例,而itemRenderer的data属性就会取得dataProvider中相应数据项的数据。
				this.product = value as Product;//此处是转换value的类型,从Object转为Product
			}			
		]]>
	</fx:Script>
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
	<s:VGroup id="products">
		<s:Label text="{product.prodName}" id="prodName"/>
		<mx:Image scaleContent="true" source="assets/{product.imageName}" 
				  mouseOver="this.currentState='expanded'"
				  mouseOut="this.currentState='State1'"/>
		<s:Label text="${product.listPrice}" id="price"/>
		<s:Button label="AddToCart" id="add"
				  click="addToCart( product )"/><!--先派发click事件,继而通过click处理函数派发addProduct事件-->
		<s:Button label="Remove From Cart" id="remove"
				  click="removeFromCart( product )"/><!--先派发click事件,继而通过click处理函数派发removeProduct事件-->

	</s:VGroup>
	<s:VGroup includeIn="expanded" x="200" width="100%">
		<s:RichText text="{product.description}"
					width="50%"/>
		<s:Label text="Certified Organic"
				 visible="{product.isOrganic}"/>
		<s:Label text="Low Fat"
				 visible="{product.isLowFat}"/>
	</s:VGroup>		
</s:DataRenderer>


更正一下建项目时的顺序,前面写的可能不对,下面写的是自己想了想右写的。

(1)主界面

(2)远程数据获取对象(services包)

(3)将主界面细分为各个组件(components包)

(4)值对象(vo包)

(5)业务逻辑(services包)

(6)重构(events包会在重构时起作用,因为每一个事件对象都可以包含自己的信息,通过事件分发和监听来实现一些操作,比如加入购物车、从购物车中删除等,就会减少new 的使用,这样会达到松散耦合的效果。此外,Flex使用基于事件或者说事件驱动的编程模型,这就意味着事件决定应用程序的流程)


这些只是暂时看完前11课后的小总结,可能以后还会有更加好的重构方法,未完,再续。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值