很喜欢曾经看到的一句话:以输出倒逼输入。以输出的形式强制自己学习,确实是高效的学习方式,真的很棒。以下仅为个人学习理解,如有错误,欢迎指出,共同学习。


1. 什么是Lightning Component框架?

 Lightning Component框架是一个UI框架,用于为移动和台式设备开发Web应用程序。这是一个单页面Web应用框架,用于为Lightning Platform应用程序构建具有动态,响应式用户界面的单页应用程序。它在客户端使用JavaScript,在服务器端使用Apex。

Lightning Component作为Web应用框架,可以轻松的创建自定义应用程序,而不必自己编写全部代码。常用的Web应用程序框架有很多, 例如:Ruby on Rails, Grails, AngularJS, Django, CakePHP等等,甚至前面提到的Visualforc component也是一种web框架。

当然,Lighnting Component也可以看成是CS架构。

客户端主要由两个元素组成:View和Controller

  • View:是XML markup,同时混合了自定义的Aura component静态HTML标签,例如:<aura:component>标签。如果有过Visualforce经验的小伙伴一定对该格式比较熟悉:namespace:tagName。对于Aura的组件,Salesforce提供了非常完善的参考,各种不同的组件都已经给出参考示例,大大减少了开发和学习成本。具体的地址:https://developer.salesforce.com/docs/component-library/overview/components
  • Controller:主要是由JavaScript语言编写,其目的主要是和服务端进行绑定,获取所需的数据,并提供给View进行展示。

服务端主要也有两个元素组成:Controller和Database。

  • Controller: 由Apex语言开发(类似于Java语言),Apex与Java一样,由一个个类文件组成,不同的是Java为.java文件,而Apex为.cls文件。注意,在客户端的View文件中绑定的是类名称
  •  Database: 使用数据操作语言DML(Data Manipulation Language)对数据进行插入,更新,删除和创建操作。

2. Aura组件捆绑包

Aura组件便是基于Lighnting Component框架进行的二次开发。

2.1 组件的命名规则

创建组件时,其命名的规则必须满足如下条件:

  • 必须以字母开头
  • 必须仅包含字母数字或下划线字符
  • 在命名空间中唯一
  • 不能包含空格
  • 不能以下划线结尾
  • 不能包含两个连续的下划线

2.2 组件创建的文件

当我们在工程中创建一个新的Aura捆绑包(以下捆绑包都称为组件)时,工程会自动创建出.auradoc,.cmp,.xml,.css,.design,svg,controller.js,help.js,renderer.js几个文件。

资源资源名称用途
componenttestAura.cmp在捆绑包中唯一的必要资源,包含了组件的标记,并且每个捆绑包中只有一个component。
CSS样式testAura.css组件的形状格式
DesigntestAura.design当组件在Lightning App Builder或者Lightning Page中使用时需要用到该文件
HelpertestAuraHelper.jsJavascript函数,该函数可以被捆绑包中的任何javascript代码调用
DocumentationtestAura.auradoc对组件的一些简单介绍说明
RenderertestAuraRenderer.js客户端渲染器会覆盖默认的渲染器
ControllertestAuraController.js客户端的控制函数,用来处理组件中的事件
SVG文件testAura.svg组件的自定义图标资源,一般为Lightning App Builder中使用的图标

 组件捆绑包中的所有资源都遵循命名规则,并且自动绑定连接。例如:<aura:component controller="TestAuraController">,组件会自动连接TestAuraController.cls类,所以组件内所有资源都可连接该控制类。

2.3 组件的工作原理

组件由自动创建的一系列文件组成,并且每个文件都发挥着不同的功能。其中,组件的主体便是component(.cmp文件),对于最精简的组件来讲,只修改.cmp文件即可(其他文件使用默认值),该文件为组件定义了视图。

当然,对于实际项目开发中,仅仅含有视图是远远不够的。通常,我们需要修改controller.js和helper.js文件。controller.js与.cmp文件交互,提供视图中所需要的数据;helper.js与服务器controller.cls交互,获取数据库中的数据;controller.js直接调用helper.js中的函数(当然,可以把helper.js中的函数直接写在controller.js中,直接从controller.js中获取数据库中的数据,但该模式不便与维护,不推荐使用)。

如果组件需要与服务器中数据库进行交互,则还需创建一个Apex控制类,与控制类与数据库交互,并将数据传递给组件。

不同文件之间的联系,如下图所示:

3. 组件的命名空间

3.1 命名空间的适用场景

每个组件都是命名空间的一部分,如果Org中设置了命名空间前缀,那么需使用该命名空间访问组件。否则,使用默认命名空间访问组件,系统默认的命名空间为“c”。

  • 如果Org没有创建命名空间前缀,下述情况必须使用“c”命名空间前缀:
    • 引用自定义创建的组件
    • 引用自定义创建的事件
  • 如果Org没有创建命名空间,下述情况下Org会自动使用隐式命名空间,即该场景下无需使用指定的命名空间前缀:
    • 引用自定义对象
    • 引用标准对象和自定义对象的字段
    • 引用Apex的控制类
  • 如果Org创建了命名空间前缀,下述情况下必须使用自定义的命名空间前缀:
    • 引用自定义创建的组件
    • 引用自定义创建的事件
    • 引用自定义对象
    • 引用标准对象和自定义对象的字段
    • 引用Apex的控制类
    • 引用静态资源

3.2 命名空间命名规则

命名规则必须满足以下条件:

  • 以字母开头
  • 包含1-15个字母数字字符
  • 不包含两个下划线

例如: myNamespace123和my_namespace是有效的;123MyNamespce和my__namespace是无效的。

3.3 创建命名空间

Setup-->Packages(注意:该条目只在Salesforce Classic版本中才有)-->Developer Settings-->Edit

Check Avaliability校验名称是否满足规则。

3.4 命名空间使用示例

  • Org没有设置命名空间前缀
引用项示例
标记中使用组件<c:myComponent>
系统属性中使用组件

<aura:component extends="c:myComponent">
<aura:component implements="c:myInterface">

Apex控制类<aura:component controller="ExpenseController">
属性的类型为自定义对象<aura:attribute name="expense" type="Expense__c" /> 
属性的类型为自定义对象,并且设置默认值
<aura:attribute name="newExpense" type="Expense__c"
    default="{ 'sobjectType': 'Expense__c',
               'Name': '',
               'Amount__c': 0,
               …
    }" />
表达式中含有自定义对象的字段<ui:inputNumber value="{!v.newExpense.Amount__c}" label=… />
javascript函数中含有自定义对象字段
updateTotal: function(component) {
    …
    for(var i = 0 ; i < expenses.length ; i++){
        var exp = expenses[i];
        total += exp.Amount__c;
    }
    …
}
在Javascript函数中动态创建新的组件
var myCmp = $A.createComponent("c:myComponent", {},
    function(myCmp) { }
);
在Javascript函数中的接口对比aCmp.isInstanceOf("c:myInterface")
注册事件<aura:registerEvent type="c:updateExpenseItem" name=… />
事件处理<aura:handler event="c:updateExpenseItemaction=… />
显式依赖<aura:dependency resource="markup://c:myComponent" />
Javascript函数中的应用事件var updateEvent = $A.get("e.c:updateExpenseItem");
静态资源<ltng:require scripts="{!$Resource.resourceName}styles="{!$Resource.resourceName}" />
  • Org设置了命名空间前缀
引用项示例
标记中使用组件<yournamespace:myComponent />
系统属性中使用组件

<aura:component extends="yournamespace:myComponent">
<aura:component implements="yournamespace:myInterface">

Apex控制类<aura:component controller="yournamespace.ExpenseController">
属性的类型为自定义对象<aura:attribute name="expenses" type="yournamespace__Expense__c[]" />
属性的类型为自定义对象,并且设置默认值
<aura:attribute name="newExpense" type="yournamespace__Expense__c"
    default="{ 'sobjectType': 'yournamespace__Expense__c',
               'Name': '',
               'yournamespace__Amount__c': 0,
               …
    }" />
表达式中含有自定义对象的字段<ui:inputNumber value="{!v.newExpense.yournamespace__Amount__c}" label=… />
javascript函数中含有自定义对象字段
updateTotal: function(component) {
    …
    for(var i = 0 ; i < expenses.length ; i++){
        var exp = expenses[i];
        total += exp.yournamespace__Amount__c;
    }
    …
}
在Javascript函数中动态创建新的组件
var myCmp = $A.createComponent("yournamespace:myComponent",
    {},
    function(myCmp) { }
);
在Javascript函数中的接口对比aCmp.isInstanceOf("yournamespace:myInterface")
注册事件<aura:registerEvent type="yournamespace:updateExpenseItem" name=… />
事件处理<aura:handler event="yournamespace:updateExpenseItem" action=… />
显式依赖<aura:dependency resource="markup://yournamespace:myComponent" />
Javascript函数中的应用事件var updateEvent = $A.get("e.yournamespace:updateExpenseItem");
静态资源<ltng:require scripts="{!$Resource.yournamespace__resourceName}styles="{!$Resource.yournamespace__resourceName}" />

4 组件的主体

4.1 配置项

在创建Aura组件时,可在该文件中配置组件的配置选项。配置选项都是可选的,所以可以进行任意组合。

在Aura组件中提供如下配置项:

配置标记描述
Lightning Tabimplements="force:appHostable"创建一个组件,该组件可以作用Lightning Experience或者Salesfroce手机App的导航元素
Lightning Pageimplements="flexipage:avaliableForAllPageTypes" and access="global"创建一个组件,该组件可以用在Lightning页面或者Lightning App Builder中
Lighnting Record Pageimplements="flexipage:availableForRecordHome, force:hasRecordId" and access="global"创建一个组件,该组件可以用在Lightning Experience的记录的Home页面
Lighnting Communities Page

implements="forceCommunity:availableForAllPageTypes" and access="global"

创建一个组件,该组件支持在Community Builder中拖拽功能
Lighnting Quick Actionimplements="force:lightningQuickAction"创建一个组件,该组件可以充当一个Lightnging quick action

示例:

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes">
</aura:component>

4.2 组件属性

组件属性类似与Apex中类的成员变量(或者说Java中类的成员变量)。他们是组件在特定的实例上设置的类型化字段,可以使用表达式语法从组件的标记内引用他们。

语法:<aura:attribute name="**" type="**" default="**" required="true/false" access="**" description="**"> 

  • name:必要字段,属性的名称
  • type:必要字段,属性的类型,支持的类型见下面的“属性type支持的类型”
  • default:非必要字段,默认值类型与type一致。
  • required:非必要字段,标记该属性是否为必须字段。true:表该字段为必要字段;false:表该字段为非必要字段。
  • access: 非必要字段,表该属性是否可被所属命名空间之外使用。public(默认):所有命名空间皆可用;global:应用内可使用;private: 组件内可使用。
  • description: 非必要字段,对该属性进行简单的描述。

示例:

<aura:component>
    <aura:attribute name="whom" type="String" default="world"/>
    Hello {!v.whom}!
</aura:component>

1) 属性命名规则:

  • 必须以字母或者下划线开头
  • 必须仅包含字母数字或者下划线字符

2) 属性type支持的类型

aura:attribute支持的类型有以下几种:基础类型,函数类型,对象类型,标准和自定义对象类型,集合类型,Apex Class类型,指定框架类型。

  • 基础类型
类型示例描述
Boolean<aura:attribute name="showDetail" type="Boolean" />值为true/false
Date<aura:attribute name="startDate" type="Date" />日期类型,格式为:yyyy-mm-dd。hh:mm:ss没有保存。
DateTime<aura:attribute name="lastModifiedDate" type="DateTime" />

日期类型,对应时间戳格式。

保存了除了日期,还保存了时间,并且精确到毫秒。

Decimal<aura:attribute name="totalPrice" type="Decimal" />

十进制,可以包括小数部分。对应Java.math.BigDecimal,精度高于Double类型。

针对货币字段,一般选择该类型。

Double<aura:attribute name="widthInchesFractional" type="Double" />Double类型,可以包含小数位。对应Java.lang.Double。
Integer<aura:attribute name="numRecords" type="Integer" />整数类型,不包含小数位。对应Java.lang.Integer。
Long<aura:attribute name="numSwissBankAccount" type="Long" />长整型,不包含小数位。对应Java.lang.Long。
String<aura:attribute name="message" type="String" />字符串类型。

示例:

<aura:attribute name="favoriteColors" type="String[]" default="['red','green','blue']" />
  • 函数类型

属性的类型可以对象Javascript中的某个函数。如果子组件具有该类型的属性,可传递回调函数给父组件。

示例:

<aura:attribute name="callback" type="Function" />

注意:该类型不适用于服务端,仅在客户端使用。

  • 对象类型

该类型的属性对应一个对象。

示例:

<aura:attribute name="data" type="Object" />

注意:一般情况下,不建议使用该类型。object类型的属性在传递至服务端时,会将所有的东西序列化为字符串,此时如果使用深度表达(例如:v.data.property),则会抛出字符串没有该属性异常。因此,尽量使用type="Map",防止出现反序列化等问题。

  • 标准或自定义对象类型

属性支持标准或自定义对象的类型。

示例:

<aura:attribute name="acct" type="Account" />
<aura:attribute name="expense" type="Expense__c" />

注意:用户至少对该对象具有读取权限,否则组件不会加载。

  • 集合类型

下面为支持的集合类型:

类型示例描述
type[](Array)<aura:attribute name="colorPalette" type="String[]" default="['red', 'green', 'blue']" />自定义数组
List<aura:attribute name="colorPalette" type="List" default="['red', 'green', 'blue']" />有序的列表
Map<aura:attribute name="sectionLabels" type="Map" default="{ a: 'label1', b: 'label2' }" />

key:value集合。key不可重复。

如果不设置默认值,则在Javascript中默认设为null。

如果想设置空值,可写为:default="{}"

Set<aura:attribute name="collection" type="Set" default="['red', 'green', 'blue']" />集合,无序,不含重复元素。

示例:

<aura:component controller="TestAuraController" access="global">
    <aura:attribute name="selectedDisplayMonth" type="String" default="6 Months,12 Months,18 Months,24 Months,36 Months" />
    <aura:iteration items="{!v.displayMonths}" var="displayMonth">
          {!displayMonth}
    </aura:iteration>
</aura:component >
  • Apex Class类型

该类型属性对应一个Apex类。

示例:

存在某个自定义Apex类:TestAura、

<aura:attribute name="color" type="docSampleNamespace.TestAura" />
  • 指定框架类型

下面为支持的指定框架类型:

类型示例描述
Aura:componentN/A

一个单独的组件。

相比较而言,官方推荐使用Aura:component[]类型。

Aura:component[]
<aura:component>
    <aura:attribute name="detail" type="Aura.Component[]">
    <p>default paragraph1</p>
    </aura:attribute>
    Default value is: {!v.detail}
</aura:component>
利用该类型可以设置一个类型块。 
 Aura.Action<aura:attribute name =“ onclick” type =“ Aura.Action” />  使用此类型,可以将action传递给组件。

4.3 表达式

在3.4.2的组件属性示例中,新建了一个属性whom, 引用该属性时使用了表达式:{!v.whom},负责该属性的动态输出。

语法:{!expression}

上述示例中,我们的属性名称定义为whom,v表示视图(View)。当组件使用时,表达式的值将被评估并且动态替换。

注意:表达式区分大小写。空格忽略。如果自定义字段为myNamespace__Amount__c,要获取该属性值,必须写为:{!v.myObject.myNamespace__Amount__c}

1) 表达式动态输出

利用表达式是最简单的值动态输出方式。

表达式的值可以来自:component属性,具体的数字,布尔值等。

示例:

component属性:{!v.whom} ==> 输出属性名为whom的值
文字值:{!123}, {!'abc'} ==> 输出分别为:123, abc
布尔值:{!true}, {!false} ==> 输出分别为:true,false

注意:文字值中,“!”后面可以直接跟数字值,如果是字符则需要用单引号' '包起来,不包含则组件不会加载,用双引号会报错。

2) 条件表达式

  • 三元表达式

与所有语言一样,这里也支持三元表达式,想必大家对三元表达式的概念都很清楚,这里就不再解释了。

示例:

{!v.displayMonth == '' ? 'No value' : 'Has value'} 
displayMonth属性值不为空字符,打印:Has value;
displayMonth属性值为空字符,打印:No value
  • <aura:if>标记 

类似与Java中if-else

示例:

<aura:component>
    <aura:attribute name="read" type="Boolean" default="false" />
    <aura:if isTrue="{!v.read}">
        you can read it.
        <aura:set attribute="else">
            you cannot read it.
        </aura:set>
    </aura:if>
</aura:component>    

read属性值为:true,打印:you can read it.

read属性值为:false,打印:you cannot read it.

3) 不同组件间数据绑定

当我们在在一个View中添加另一个组件,可以在父组件中初始化子组件的属性值。目前有两种语法格式:

语法1: <c:childComponent childAttr="{!v.parentAttr}" />

绑定语法,将父组件中的parentAttr属性和子组件的childAttr属性关联,初始化时将parentAttr的值传递给childAttr。运行中修改任意一个属性,都会导致另外一个属性值的改变。

示例:

parentAura.cmp

<!--Parent component-->
<aura:component access="global">
    <aura:attribute name="parentAttr" type="String" default="Parent Attribute" />
    <!--实例化childAura组件-->
    <c:childAura childAttr="{!v.parentAttr}" />
    <br/>
    parentAttr in parent: {!v.parentAttr}
    <div style="background:white">
        <lightning:button label="Apply" onclick="{!c.applyHandle}" disabled="false" />
    </div>
</aura:component>

parentAuraController.js

({
    applyHandle: function (cmp, event, helper) {
        cmp.set('v.parentAttr', 'Parent update');
    }
})

childAura.cmp

<!--Child component-->
<aura:component>
    <aura:attribute name="childAttr" type="String" default="Child Attribute"/>
    <div class="slds-p-top--large" tyle="background:white">
        childAttr in child: {!v.childAttr}
        <lightning:button label="Apply" onclick="{!c.applyHandle}" disabled="false" />
    </div>
</aura:component>    

childAuraController.js

({
    applyHandle : function(component, event, helper) {
        component.set('v.childAttr', 'Child update');
    }
})

output:

childAttr in child: Parent Attribute
parentAttr in parent: Parent Attribute
点击childAura组件的apply按钮
childAttr in child: Child update parentAttr in parent: Child update
点击parentAura组件的apply按钮
childAttr in child: Parent update parentAttr in parent: Parent update

语法2: <c:childComponent childAttr="{#v.parentAttr}" />

非绑定语法,将父组件中的parentAttr属性和子组件的childAttr属性关联,初始化时将parentAttr的值传递给childAttr。运行中修改任意一个属性,只改变当前属性值,不会修改另外一个属性值。

示例:

parentAura.cmp

<!--Parent component-->
<aura:component access="global">
    <aura:attribute name="parentAttr" type="String" default="Parent Attribute" />
    <!--实例化childAura组件-->
    <c:childAura childAttr="{#v.parentAttr}" />
    <br/>
    parentAttr in parent: {!v.parentAttr}
    <div style="background:white">
        <lightning:button label="Apply" onclick="{!c.applyHandle}" disabled="false" />
    </div>
</aura:component>

parentAuraController.js

({
    applyHandle: function (cmp, event, helper) {
        cmp.set('v.parentAttr', 'Parent update');
    }
})

childAura.cmp

<!--Child component-->
<aura:component>
    <aura:attribute name="childAttr" type="String" default="Child Attribute"/>
    <div class="slds-p-top--large" tyle="background:white">
        childAttr in child: {!v.childAttr}
        <lightning:button label="Apply" onclick="{!c.applyHandle}" disabled="false" />
    </div>
</aura:component>   

childAuraController.js

({
    applyHandle : function(component, event, helper) {
        component.set('v.childAttr', 'Child update');
    }
})

output:

childAttr in child: Parent Attribute
parentAttr in parent: Parent Attribute
点击childAura组件的apply按钮
childAttr in child: Child update
parentAttr in parent: Parent Attribute
点击parentAura组件的apply按钮
childAttr in child: Child update
parentAttr in parent: Parent update

4.4 访问控制

Aura框架可以通过access属性自由的控制应用,组件,属性,接口,事件,方法的访问权限。access属性指定资源是否可以被所在命名空间之外使用。

使用范围

可在如下tag中使用access属性:

  • <aura:application>
  • <aura:component>
  • <aura:attribute>
  • <aura:interface>
  • <aura:event>
  • <aura:method>

access的值

  • private:
    • 可在应用,组件,接口,事件或者方法中使用, 不能被外部资源使用(命名空间)。
    • 该值可以在<aura:attribute>或<aura:method>中使用。
    • 将属性标记为private会使得将来重构变得更加简单(毕竟作用域小,所引发的影响也更小)。
    • 除了在声明该属性的组件,其他组件调用该属性时会返回undefined错误,所以即使继承自该组件的子组件也不可访问。
  •  public:
    • 在当前org中都可以访问。access的默认值便是public。
  • global:
    • 在所有的org中都可以访问。

应用访问控制

access在aura:application标签中控制app是否可被所在命名控制之外访问。

修饰符描述
public仅在当前org中可用。access的默认值。
global在所有的org中可用。

组件访问控制

access在aura:component标签中控制app是否可被所在命名控制之外访问。

修饰符描述
public仅在当前org中可用。access的默认值。
global在所有的org中可用。

属性访问控制

access在aura:attribute标签中控制app是否可被所在命名控制之外访问。 

修饰符描述
private可在应用,组件,接口,事件或者方法中使用, 不能被外部资源使用(命名空间)
public仅在当前org中可用。access的默认值。
global在所有的org中可用。

接口访问控制

access在aura:interface标签中控制app是否可被所在命名控制之外访问。 

修饰符描述
public仅在当前org中可用。access的默认值。
global在所有的org中可用。

事件访问控制

access在aura:event标签中控制app是否可被所在命名控制之外访问。 

修饰符描述
public仅在当前org中可用。access的默认值。
global在所有的org中可用。

示例:

<aura:component access="global">
    ...
</aura:component>

4.5 组件标记

在捆绑包中,以.cmp为后缀的文件称为标记(Markup,可以理解为视图),是捆绑包中唯一的必要资源,所以最精简的捆绑包只包含一个.cmp文件即可。

标记可以包含文本或其他组件的引用,当然也可以声明当前组件的元数据。

Hello, World!示例:

<aura:component>
    Hello, world!
</aura:component>

在<aura:component>标签中包含“Hello, world!”文本,当引用该组件时,会打印出“Hello, world”

在markup中集成了绝大多数HTML的标签,例如<div>, <span>以及<br>等等。(也支持HTML5标签)

示例:

<aura:component>
    <div class="container">
        <!--Other HTML tags or components here-->
    </div>
</aura:component>

4.6 css样式

组件的样式,我们一般在.css后缀文件中定义。

组件中的所有顶级元素都添加了一个特殊的.THIS CSS类,将命名空间添加到CSS文件中,可以有效防止当前组件的CSS样式被其他组件的CSS文件覆盖。如果CSS文件不按照该格式编写,框架会抛错误。

示例:

testAura.cmp

<aura:component>
  <!--使用CSS中.THIS .WHITE类-->
  <div class="white">
    Hello, world!
  </div>

  <!--顶级元素使用.THIS类-->
  <h2>Check out the style in this list.</h2>

  <div>
    <!--使用.THIS .RED类-->
    <li class="red">I'm red.</li>
    <!--使用.THIS .BLUE类-->
    <li class="blue">I'm blue.</li>
    <!--使用.THIS .GREEN类-->
    <li class="green">I'm green.</li>
    <!--没有指定,使用当前模块样式-->
    <li>I'm default.</li>
  </div>
</aura:component>

testAura.css

.THIS {
    background-color: grey;
}

.THIS.white {
    background-color: white;
}

.THIS .red {
    background-color: red;
}

.THIS .blue {
    background-color: blue;
}

.THIS .green {
    background-color: green;
}

输出:

分析:从产生的结果来看,<h2>是顶级元素,直接使用了.css文件中.THIS类得到灰色背景;“I'm default”没有指定颜色,使用当前模块<div>的样式,而<div>是顶级元素,所以使用.THIS类得到灰色背景;其他的指定CSS类,显示对应样式。

5. 实战案例分析

5.1 Parent组件

parentAura.cmp

<!--Parent component-->
<!--controller类名:ParentAuraController-->
<!--force:appHostable: 该组件可作为Lightning Experience的导航元素-->
<!--flexipage:availabeForAllPageTypes: 可在Lightning App Builder中使用,也做作为Page使用-->
<!--access=global: 该组件在所有的Orgs中都可以被引用-->
<aura:component controller="ParentAuraController"
                implements="force:appHostable,flexipage:availableForAllPageTypes"
                access="global">

    <aura:attribute name="displayMonths" type="String[]" />
    <aura:attribute name="selectedDisplayMonth" type="String" />
    <aura:attribute name="displayMonth" type="String" default="Last 6 Months"/>
    <aura:attribute name="read" type="Boolean" default="false" />

    <!--组件初始化操作-->
    <aura:handler name="init" value="{!this}" action="{!c.handleInit}" />

    <div class="white">
        <lightning:layout multipleRows="true">
            <lightning:layoutItem size="4" padding="around-small">
                <!--下拉框选择组件,selectedDisplayMonth为下拉框选择的值,displayMonths为下拉框值列表-->
                <!--onchange: selectedDisplayMonth值改变时,调用controller.js中changeDisplayMonth函数-->
                <lightning:select name="displayMonthId" label="Select display months" aura:id="displayMonthId"
                    value="{!v.selectedDisplayMonth}" required="true" onchange="{!c.changeDisplayMonth}">
                    <aura:iteration items="{!v.displayMonths}" var="displayMonth">
                        <option text="{!displayMonth}"></option>
                    </aura:iteration>
                </lightning:select>
            </lightning:layoutItem>

            <lightning:layoutItem size="6" padding="around-small">
                <div class="slds-p-top--large">
                    <!--按钮组件,label为界面显示值;onclick: 点击按钮时触发controller.js中applyHandle函数-->
                    <!--display: true表示按钮灰掉,无法操作;false表示正常工作-->
                    <lightning:button label="parentApply" onclick="{!c.applyHandle}" disabled="false" />
                </div>
            </lightning:layoutItem>
        </lightning:layout>
        <lightning:layout multipleRows="true">
            <lightning:layoutItem size="12" padding="around-small">
            <li>
                <!--三元表达式-->
                <aura:if isTrue="{!v.read}">
                    you can read it.
                    <aura:set attribute="else">
                        you cannot read it.
                    </aura:set>
                </aura:if>
            </li>
            <li>displayMonth in parent: {!v.displayMonth}</li>
            </lightning:layoutItem>
        </lightning:layout>
        <lightning:layout multipleRows="true">
            <lightning:layoutItem size="12" padding="around-small">
                <!--实例化childAura组件-->
                <c:childAura childDisplayMonth="{!v.displayMonth}" />
            </lightning:layoutItem>
        </lightning:layout>
    </div>
</aura:component>    

parentAura.css

.THIS {
    background-color: grey;
}

.THIS.white {
    background-color: white;
}

parentAuraController.js

({
    handleInit: function (cmp, event, helper) {
        // 初始化组件时,调用Help.js中getDisplayMonths函数,获取下拉框值列表
        helper.getDisplayMonths(cmp);
    },

    changeDisplayMonth: function (cmp, event, helper) {
        console.log("displayMonths: " + cmp.get('v.displayMonths'))
        console.log("selected displayMonth: " + cmp.get('v.selectedDisplayMonth'));

    },

    applyHandle: function (cmp, event, helper) {
        // 点击parentApply按钮时,将下拉框选中的值赋值给属性displayMonth
        cmp.set('v.displayMonth', cmp.get('v.selectedDisplayMonth'));
        // 点击parentApply按钮时,将true赋值给属性read.
        cmp.set('v.read', "true");
        console.log("after click apply, displayMonth: " + cmp.get('v.displayMonth'));
    }
})

parentAuraHelper.js

({
    getDisplayMonths : function(cmp) {
        // 获取controll.cls类中getDisplayMonths函数
        var action = cmp.get("c.getDisplayMonths");
        // 为该函数设置回调函数
        action.setCallback(this, function (response) {
            var status = response.getState();
            console.log("get displayMonths: " + status);
            // 判断调用controller.cls类getDisplayMonths函数的响应状态码
            if (status == "SUCCESS") {
                // 解析controller.cls传回的响应,并赋值给变量repsonseBody
                var responseBody = JSON.parse(response.getReturnValue());
                // 将变量responseBody赋值给组件属性displayMonths(下拉框值列表)
                cmp.set("v.displayMonths", responseBody);
            }
        });
        // 执行获取数据行动
        $A.enqueueAction(action);
    }
})

ParentAuraController.cls

public with sharing class ParentAuraController {
    @AuraEnabled
    public static String getDisplayMonths() {
        List<String> displayMonths = new List<String>();
        displayMonths.add('Last 6 Months');
        displayMonths.add('Last 12 Months');
        displayMonths.add('Last 18 Months');
        displayMonths.add('Last 36 Months');
        // 将响应序列化为Json格式
        return JSON.serialize(displayMonths);
    }
}

5.2 Child组件

childAura.cmp

<!--Child component-->
<aura:component>
    <aura:attribute name="childDisplayMonth" type="String" default="child"/>
    <div class="slds-p-top--large">
        <lightning:layout multipleRows="false">
            <lightning:layoutItem size="4" padding="around-small">
                displayMonth in child: {!v.childDisplayMonth}
            </lightning:layoutItem>
            <lightning:layoutItem size="4" padding="around-small">
                <lightning:button label="childApply" onclick="{!c.applyHandle}" disabled="false" />
            </lightning:layoutItem>
        </lightning:layout>
    </div>
</aura:component>    

childAura.css

.THIS {
    background-color: LightSkyBlue;
}

childController.js

({
    applyHandle : function(component, event, helper) {
        component.set('v.childDisplayMonth', 'Last 36 Months');
    }
})

5.3 案例分析

加载后如下图所示:

分析:

  • 初始化parentAura组件时,从controller.cls中获取displayMonths值列表["Last 6 Months", "Last 12 Months", "Last 18 Months", "Last 36 Months"],默认加载第一个值,所以下拉框中为Last 6 Months.
  • read属性的默认值设为false,所以三元表达式中选择else项,打印:you cannot read it.
  • displayMonth的默认值设置为Last 6 Months, 打印:displayMonth in parent: Last 6 Months.
  • 在parentAura组件中初始化childAura组件时,传递childDisplayMonth值等于displayMonth,所以该属性值为Last 6 Months,而不使用默认值child,打印displayMonth in child: Last 6 Months.  

更换下拉框值,并点击parentApply按钮:

分析:

  • 下拉框选择Last 12 Months,点击parentApply按钮时,调用parentAuraController.js中applyHandle函数。该函数中,将selectedDisplayMonth赋值给displayMonth,打印:displayMonth in parent: Last 12 Months;将read属性重新赋值为true,所以三元表达式中选择if项,打印:you can read it.
  • 在parentAura组件中实例化childAura组件时,赋值childDisplayMonth采用的是绑定的方式{!**},所以修改parentAura组件中displayMonth属性值时,同步修改childAura组件中childDisplayMonth值。(自己可以尝试非绑定方式,查看结果如何)

点击childParent按钮:

分析:

  • 点击childApply按钮,触发childAura组件childAuraController.js的applyHandle函数,该函数重新赋值属性childDisplayMonth等于Last 36 Months,打印:displayMonth in child: Last Months
  • 在parentAura组件中实例化childAura组件时,赋值childDisplayMonth采用的是绑定的方式{!**},所以修改childAura组件中childDisplayMonth属性值时,同步修改parentAura组件中displayMonth值。(自己可以尝试非绑定方式,查看结果如何)

作者:吴家二少

博客地址:https://www.cnblogs.com/cloudman-open/

本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接

01-02 23:18