MXMLでのコンポーネントの継承の方法

MXMLファイルを共通化するために、それ自体を親クラスにすることは少ないと思いますが、今回そのような機会があったので覚え書きです。

**パッケージ構成**
![mate_package.png](https://qiita-image-store.s3.amazonaws.com/0/3184/8fb98c27-b33b-4041-6d17-6f379c8966e1.png)

**ソースコード**

***Indexファイル***

まずは、Parent.mxmlを継承した ChildA.mxml/ChildB.mxml/ChildC.mxmlを配置します。

```Index.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"
			   minWidth="955"
			   minHeight="600"
			   xmlns:view="main.view.*"
			   xmlns:map="main.map.*">

	<fx:Script>
		<![CDATA[
			protected function change_value(event:MouseEvent):void
			{
				childA.model.strValue="イベント発生!!";
			}
		]]>
	</fx:Script>

	<fx:Declarations>
		<!-- 使用するEventMapを 以下に追記する -->
		<map:ParentEventMap/>

	</fx:Declarations>

	<s:VGroup top="20"
			  left="20">
		<!--Child Viewを配置する-->
		<s:HGroup gap="10">
			<view:ChildA click="change_value(event)"
						  id="childA"/>
			<view:ChildB id="childB"/>
			<view:ChildC id="childC"/>
		</s:HGroup>
	</s:VGroup>
</s:Application>
```


***EventMap***

イベントマップでモデルクラスをインスタンス化し、各子Viewに親となるParentModelをインジェクトします。

```ParentEventMap.mxml
<?xml version="1.0" encoding="utf-8"?>
<mt:EventMap 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:mt="http://mate.asfusion.com/">

	<fx:Script>
		<![CDATA[
			import extend.model.ParentModel;
			import extend.view.ChildA;
			import extend.view.ChildB;
			import extend.view.ChildC;
			import extend.view.Parent;

			import mx.events.FlexEvent;
		]]>
	</fx:Script>

	<fx:Declarations>
		<!-- Modelのインスタンス化 dispatchを引数とする -->
		<mt:EventHandlers type="{FlexEvent.PREINITIALIZE}">
			<mt:ObjectBuilder generator="{ParentModel}"
							  constructorArguments="{scope.dispatcher}"/>
		</mt:EventHandlers>


		<!-- ViewにModelをインジェクトする -->
		<mt:Injectors target="{ChildA}">
			<mt:PropertyInjector source="{ParentModel}"
								 targetKey="model"/>
		</mt:Injectors>
		<mt:Injectors target="{ChildB}">
			<mt:PropertyInjector source="{ParentModel}"
								 targetKey="model"/>
		</mt:Injectors>
		<mt:Injectors target="{ChildC}">
			<mt:PropertyInjector source="{ParentModel}"
								 targetKey="model"/>
		</mt:Injectors>

	</fx:Declarations>
</mt:EventMap>

```

***モデルクラス***

```ParentModel.as
package extend.model
{
	import flash.events.IEventDispatcher;

	public class ParentModel
	{
		/**
		 * コンストラクタ
		 */
		public function ParentModel(dispatcher:IEventDispatcher)
		{
			this.dispatcher=dispatcher;
			this.strValue="クリックしてください。"
		}
		protected var dispatcher:IEventDispatcher;

		/**
		 * Childで使用する変数
		 */
		private var _strValue:String;

		[Bindable]
		public function get strValue():String
		{
			return _strValue;
		}

		public function set strValue(value:String):void
		{
			_strValue=value;
		}
	}
}
```

***親MXMLファイル***

親クラスでは、[Bindable]にてModel変数を宣言します。

```Parent.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"
		 width="200"
		 height="40">

	<fx:Script>
		<![CDATA[
			import extend.model.ParentModel;
			import mx.events.FlexEvent;

			[Bindable]
			public var model:ParentModel;
		]]>
	</fx:Script>
</s:Group>
```

***子MXMLファイル***

```ChildA.mxml
<?xml version="1.0" encoding="utf-8"?>
<view:Parent 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:view="extend.view.*">

	<s:HGroup>
		<s:Label text="Child A"/>
		<s:TextInput text="{this.model.strValue}"/>
	</s:HGroup>
</view:Parent>
```

```ChildB.mxml
<?xml version="1.0" encoding="utf-8"?>
<view:Parent 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:view="extend.view.*">

	<s:HGroup>
		<s:Label text="Child B"/>
		<s:TextInput text="{this.model.strValue}"/>
	</s:HGroup>
</view:Parent>
```

```ChildC.mxml
<?xml version="1.0" encoding="utf-8"?>
<view:Parent 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:view="extend.view.*">

	<s:HGroup>
		<s:Label text="Child C"/>
		<s:TextInput text="{this.model.strValue}"/>
	</s:HGroup>
</view:Parent>
```

***実行結果***

結果としては、ChildA.mxml/ChildB.mxml/ChildC.mxmlは、同一の親Modelをインジェクトされている為、親Modelで定義している変数値を、同様の結果として表示します。

![mate_before.png](https://qiita-image-store.s3.amazonaws.com/0/3184/3532a27e-fbd3-503b-4fef-10fbdfc8826b.png)


![mate_after.png](https://qiita-image-store.s3.amazonaws.com/0/3184/9714a776-c7f1-f7ee-cb77-dc13d92d9791.png)

まあ、滅多に無いケースだと思いますが・・・。
変数の参照の検証として。