很喜欢曾经看到的一句话:以输出倒逼输入。以输出的形式强制自己学习,确实是高效的学习方式,真的很棒。以下仅为个人学习理解,如有错误,欢迎指出,共同学习。
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几个文件。
资源 | 资源名称 | 用途 |
component | testAura.cmp | 在捆绑包中唯一的必要资源,包含了组件的标记,并且每个捆绑包中只有一个component。 |
CSS样式 | testAura.css | 组件的形状格式 |
Design | testAura.design | 当组件在Lightning App Builder或者Lightning Page中使用时需要用到该文件 |
Helper | testAuraHelper.js | Javascript函数,该函数可以被捆绑包中的任何javascript代码调用 |
Documentation | testAura.auradoc | 对组件的一些简单介绍说明 |
Renderer | testAuraRenderer.js | 客户端渲染器会覆盖默认的渲染器 |
Controller | testAuraController.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"> |
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:updateExpenseItem" action=… /> |
显式依赖 | <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"> |
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 Tab | implements="force:appHostable" | 创建一个组件,该组件可以作用Lightning Experience或者Salesfroce手机App的导航元素 |
Lightning Page | implements="flexipage:avaliableForAllPageTypes" and access="global" | 创建一个组件,该组件可以用在Lightning页面或者Lightning App Builder中 |
Lighnting Record Page | implements="flexipage:availableForRecordHome, force:hasRecordId" and access="global" | 创建一个组件,该组件可以用在Lightning Experience的记录的Home页面 |
Lighnting Communities Page |
implements="forceCommunity:availableForAllPageTypes" and access="global" |
创建一个组件,该组件支持在Community Builder中拖拽功能 |
Lighnting Quick Action | implements="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:component | N/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/
本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接