Lightning Component の継承の説明がいまいち分かりづらかったので、ちょっとしたサンプルを書いてみました。
基本的なコンポーネントの動きの確認
基本的なコンポーネントの動き
BasicComponent.cmp
<aura:component implements="forceCommunity:availableForAllPageTypes" access="public" >
<!-- Application Event Handler -->
<aura:handler name="init" value="{!this}" action="{!c.controllerMethod}" />
</aura:component>
BasicComponentController.js
({
controllerMethod : function(cmp, event, helper) {
console.log('controllerMethod!');
helper.helperMethod(cmp, helper);
},
})
BasicComponentHelper.js
({
helperMethod : function() {
console.log('helperMethod!');
}
})
検証結果
controllerMethod!
helperMethod!
ポイント
- コミュニティビルダーで動作確認をするため、
forceCommunity:availableForAllPageTypes
をインプリメントしています -
init
イベントをトリガに、コントローラメソッド、ヘルパーメソッドを呼び出します。
継承関係を構築する
スーパーコンポーネント
SuperComponent.cmp
<aura:component access="global" extensible="true">
<!-- Application Event Handler -->
<aura:handler name="init" value="{!this}" action="{!c.controllerMethod}" />
<!-- User Interface -->
{!v.body}
</aura:component>
SuperComponentController.js
({
controllerMethod : function(cmp, event, helper) {
console.log('SuperComponent.controllerMethod!');
helper.helperMethod(cmp, helper);
},
})
SuperComponentHelper.js
({
helperMethod : function(cmp, helper) {
console.log('SuperComponent.helperMethod');
}
})
サブコンポーネント
SubComponent.cmp
<aura:component access="global" extends="c:SuperComponent" implements="forceCommunity:availableForAllPageTypes">
<!-- Application Event Handler -->
<aura:handler name="init" value="{!this}" action="{!c.controllerMethod}" />
<!-- User Interface -->
{!v.body}
</aura:component>
SubComponentController.js
({
controllerMethod : function(cmp, event, helper) {
console.log('SubComponent.controllerMethod!');
helper.helperMethod(cmp, helper);
},
})
SubComponentHelper.js
({
helperMethod : function(cmp, helper) {
console.log('SubComponent.helperMethod');
}
})
検証結果
検証結果
SuperComponent.controllerMethod!
SuperComponent.helperMethod
SubComponent.controllerMethod!
SubComponent.helperMethod
ポイント
- スーパーコンポーネントには
extensible="true"
を記述し、サブコンポーネントにはextend="c:SuperComponent"
を記述する事で継承関係を宣言しています。 - スーパーコンポーネントには
{!v.body}
を記述し、サブコンポーネントが描画される領域を指定する必要があります。 - 継承関係があっても、それぞれのイベントハンドラがスーパーコンポーネントから順に実行されていきます。
サブコンポーネントからスーパーコンポーネントのヘルパーを継承する
スーパーコンポーネント
SuperComponent.cmp
<aura:component access="global" extensible="true">
<!-- Application Event Handler -->
<aura:handler name="init" value="{!this}" action="{!c.controllerMethod}" />
<!-- User Interface -->
{!v.body}
</aura:component>
SuperComponentController.js
({
controllerMethod : function(cmp, event, helper) {
console.log('SuperComponent.controllerMethod!');
helper.helperMethod(cmp, helper);
},
})
SuperComponentHelper.js
({
helperMethod : function(cmp, helper) {
console.log('SuperComponent.helperMethod');
}
})
サブコンポーネント
SubComponent.cmp
<aura:component access="global" extends="c:SuperComponent" implements="forceCommunity:availableForAllPageTypes">
<!-- Application Event Handler -->
<aura:handler name="init" value="{!this}" action="{!c.controllerMethod}" />
<!-- User Interface -->
{!v.body}
</aura:component>
SubComponentController.js
({
controllerMethod : function(cmp, event, helper) {
console.log('SubComponent.controllerMethod!');
helper.helperMethod(cmp, helper);
},
})
検証結果
検証結果
SuperComponent.controllerMethod!
SuperComponent.helperMethod
SubComponent.controllerMethod!
SuperComponent.helperMethod
ポイント
- サブコンポーネントはスーパーコンポーネントのヘルパーメソッドにアクセス出来ます。自身がそのヘルパーメソッドを持たない場合、スーパーコンポーネントを辿って継承関係において上に最も近いヘルパーメソッドを呼び出します。
サブコンポーネントからスーパーコンポーネントのコントローラーを継承する
スーパーコンポーネント
SuperComponent.cmp
<aura:component access="global" extensible="true">
<!-- Application Event Handler -->
<aura:handler name="init" value="{!this}" action="{!c.controllerMethod}" />
<!-- User Interface -->
{!v.body}
</aura:component>
SuperComponentController.js
({
controllerMethod : function(cmp, event, helper) {
console.log('SuperComponent.controllerMethod!');
helper.helperMethod(cmp, helper);
},
})
SuperComponentHelper.js
({
helperMethod : function(cmp, helper) {
console.log('SuperComponent.helperMethod');
}
})
サブコンポーネント
SubComponent.cmp
<aura:component access="global" extends="c:SuperComponent" implements="forceCommunity:availableForAllPageTypes">
<!-- Application Event Handler -->
<aura:handler name="init" value="{!this}" action="{!c.controllerMethod}" />
<!-- User Interface -->
{!v.body}
</aura:component>
SubComponentHelper.js
({
helperMethod : function(cmp, helper) {
console.log('SubComponent.helperMethod');
}
})
検証結果
検証結果
SuperComponent.controllerMethod!
SuperComponent.helperMethod
SuperComponent.controllerMethod!
SubComponent.helperMethod
ポイント
- サブコンポーネントはスーパーコンポーネントのコントローラーメソッドにアクセス出来ます。自身がそのコントローラーメソッドを持たない場合、スーパーコンポーネントを辿って継承関係において上に最も近いコントローラーメソッドを呼び出します。
スーパーコンポーネントからサブコンポーネントでオーバーライドされたコントローラーを呼び出す
スーパーコンポーネント
SuperComponent.cmp
<aura:component access="global" extensible="true">
<!-- Component Methods -->
<aura:method access="public" name="controllerMethod" action="{!c.controllerMethod}"
description="オーバーライドさせたいメソッドをコンポーネントメソッド化しておく" />
<!-- Application Event Handler -->
<aura:handler name="init" value="{!this}" action="{!c.controllerMethodIfOverridden}" />
<!-- User Interface -->
{!v.body}
</aura:component>
SuperComponentController.js
({
controllerMethod : function(cmp, event, helper) {
console.log('SuperComponent.controllerMethod!');
helper.helperMethod(cmp, helper);
},
controllerMethodIfOverridden : function(cmp, event, helper) {
cmp.getConcreteComponent().controllerMethod();
},
})
SuperComponentHelper.js
({
helperMethod : function(cmp, helper) {
console.log('SuperComponent.helperMethod');
}
})
サブコンポーネント
SubComponent.cmp
<aura:component access="global" extends="c:SuperComponent" implements="forceCommunity:availableForAllPageTypes">
<!-- Application Event Handler -->
<aura:handler name="init" value="{!this}" action="{!c.controllerMethod}" />
<!-- User Interface -->
{!v.body}
</aura:component>
SubComponentController.js
({
controllerMethod : function(cmp, event, helper) {
console.log('SubComponent.controllerMethod!');
helper.helperMethod(cmp, helper);
},
})
SubComponentHelper.js
({
helperMethod : function(cmp, helper) {
console.log('SubComponent.helperMethod');
}
})
検証結果
検証結果
SubComponent.controllerMethod!
SubComponent.helperMethod
SubComponent.controllerMethod!
SubComponent.helperMethod
ポイント
- オーバーライドさせたいコントローラーメソッドをコンポーネントメソッド化しておく。コンポーネントメソッドは継承される。
-
cmp.getConcreteComponent()
は、インスタンス化されたコンポーネントを返すので、スーパーコンポーネントからでもサブコンポーネントのコンポーネントメソッドにアクセスが出来るようになる。
(おまけ)サブコンポーネントのヘルパーを直接呼び出す
以前までは、cmp.getConcreteComponent().getDef().getHelper().someHelperMethod()
で直接サブのヘルパーメソッドを呼びさせていたようなのですが、いつの間にか使えなくなってしまったみたいですね。よくあるよくある。
スーパーコンポーネント
SuperComponent.cmp
<aura:component access="global" extensible="true">
<!-- Private Attributes -->
<aura:attribute access="private" name="concreteHelper" type="Object" />
<!-- Component Methods -->
<aura:method access="private" name="initConcreteHelper" action="{!c.initConcreteHelper}" />
<!-- Application Event Handler -->
<aura:handler name="init" value="{!this}" action="{!c.onValueInit}" />
<aura:handler event="aura:doneWaiting" action="{!c.callHelperMethodFromSub}" />
<!-- User Interface -->
{!v.body}
</aura:component>
SuperComponentController.js
({
onValueInit : function(cmp, event, helper) {
cmp.getConcreteComponent().initConcreteHelper();
},
initConcreteHelper : function(cmp, event, helper) {
cmp.set('v.concreteHelper', helper);
},
callHelperMethodFromSub : function(cmp, event, helper) {
cmp.get('v.concreteHelper').helperMethod(cmp, helper);
},
})
サブコンポーネント
SubComponent.cmp
<aura:component access="global" extends="c:SuperComponent" implements="forceCommunity:availableForAllPageTypes">
<!-- User Interface -->
{!v.body}
</aura:component>
SubComponentHelper.js
({
helperMethod : function(cmp, helper) {
console.log('SubComponent.helperMethod');
}
})
ポイント
-
cmp.getConcreteComponent()
とコンポーネントメソッドの応用のようなもので、サブコンポーネントのヘルパーへの参照を変数に格納しておくことで、自由に呼び出すことが出来ます。 -
init
イベントをなどでヘルパーへの参照を保存しないいけないので、init
イベントに紐付けるコントローラーメソッドはオーバーライドさせてはいけません。