看此篇博客前或者后,看一下trailhead可以加深印象以及理解的更好:https://trailhead.salesforce.com/modules/lex_dev_lc_basics
做过classic的朋友知道,前台和后台交互可以在页面上使用多种方式,比如在VF page中apex:commandButton等标签绑定action,使用actionFunction,使用ajax toolkit,使用VF Remoting或者使用action:support多种方式实现和后台的交互。如果你习惯性的使用了classic,那么你在lightning学习中可能有一点点的不适,最多的应该是没法在lightning component中使用js了,因为lightning封装了他的framework,这样的好处为后期更容易维护,不必要因为维护别人的项目各种读别人的rendered/reRender等恶心的事情,因为好多重新渲染元素的操作都在controller.js中处理了。当然,上面的都是泛泛而谈,下面细节的说一下lightning的事件驱动模型。
一.Lightning模型介绍
Lightning事件驱动模型如下图所示:
1.用户在component标签上点击按钮或者触发某个自定义事件
2.javascript controller中的action获取当前的事件源,处理业务逻辑,细节的对于后台的操作在helper中执行;
3.javascript helper中执行和server端的交互,调用后台apex controller,并在apex controller执行结束后调用回调函数去处理后期的业务逻辑以及更新UI等操作;
4.server-controller 使用apex代码处理业务逻辑以及和数据库的交互,写法和VF Remoting的后台写法类似,区别为需要在方法上添加标签@AuraEnabled。
上一篇内容说过一个component bundle包含了很多内容,此篇通过上面的事件驱动模型主要说一下以下三个元素:Component(.cmp) / Controller js(.js) / Helper js(.js)
二. Component介绍
我们在Apex中经常使用Visualforce Component做一些公用组件,但是lightning中的component和刚才说的不是一个内容。一个component是一个包含了定义着的资源信息,标签,也可以包含表达式或者是其他可选的资源,比如controller属性信息,stylesheet等信息。lightning component中头标签为<aura:component>,所有的内容均需要在此内容中编写。一个component中也可以嵌套其他的component,父子的component引用时,父的style sheet样式会影响到子,使用时需要注意此点。针对Component更重要的是这个东西用在哪里,怎么用。
1.用在哪里:
Lightning Component可以用在很多的地方,如下图所示。头标签的属性实现不同的接口,则可以将此component用于不同地方。
- implements="force:appHostable" : 创建一个componet用于自定义的lightning tab;
- implements="flexipage:availableForAllPageTypes"and access="global" 创建一个component用于lightning page或者用于lightning app builder;
- implements="flexipage:availableForRecordHome,force:hasRecordId" and access="global" 创建一个component用于lightning的记录home page,此种方式可以直接应用当前记录的ID;
- implements="forceCommunity:availableForAllPageTypes" and access="global" 创建一个component用于Community Builder;
- implements="force:lightningQuickAction" 创建一个component用于quick action。
2.怎么用:
1) 创建Lightning Component
Lightning Component可以有多种创建的方式,使用sublime创建,使用develop console或者idea,本人常用sublime创建。在File->New->Lightning Component便可以新建一个lightning component。在新建的lightning component名称处右键,便可以新建出来此lightning component bundle其他的组件,比如controller.js,helper.js等组件,如下图所示。
2) Lightning Component 基础知识
和classic 中的visualforce component很相像,一个lightning component可以嵌套另外一个lightning component,如果嵌套的component含有命名空间,则引入的方式为<yourNamespace:yourComponent/>如果没有设置命名空间,则默认的命名空间为c,即<c:yourComponent/>
一个Lightning Component文件中可以引入多种元素,常用的元素如下:
- <aura:attribute>:此标签用于声明Component中需要引用的内容信息的变量。
- <aura:registerEvent>:此标签用于引入自定义的注册事件。
- <aura:handler>:此标签用于处理自定义的注册事件以及标准的事件,比如初始化(init)等handler。
- <ltng:require>: 此标签用于引入静态资源
- 元素标签:lightning封装了很多元素标签,常用的可以归纳为容器(container)元素,按钮(button)元素,导航(navigation)元素,可视化(Visual)元素,字段(Field)元素以及格式化(format)元素。
<aura:attribute>:做过classic的朋友都知道,一个页面,后台使用成员变量,前台VF page可以用它来渲染元素。在lightning中,Component attribute很像apex中的成员变量,他们可以使用表达式语句应用在组件元素标签中进行信息渲染。
attribute必须有两个属性:name以及type, aura:attribute写法如下.
<aura:component>
<aura:attribute name="testAttribute" type="string" default="test"/>
test for {!v.testAttribute}
</aura:component>
上面的demo声明了一个类型为string的attribute,名称为testAttribute。组件如果引用相关的属性信息,引用方式为{!v. + attributeName}。lightning中,使用"v"去访问attribute内容(v可以简单的理解成view)。如果想要在后面设置attribute的值,也可以通过<aura:set attribute="anotherTestAttribute">来更改attribute值,aura:set通常可以和<aura:if>标签一起使用,有兴趣的可以自行查看。
attribute的type基本涵盖了所有的类型,type取值如下:
基本类型:
- Boolean:定义一个布尔类型attribute。eg:<aura:attribute name="showDetail" type="Boolean" />
- Date:定义一个日期类型,不含Time,默认格式:YYYY-MM-dd。 eg: <aura:attribute name="startDate" type="Date" />
- Datetime:定义一个日期类型,含Time。eg:<aura:attribute name="lastModifiedDate" type="DateTime" />
- Decimal:定义一个浮点型小数,比Double类型更容易接收currency类型的数据。eg:<aura:attributename="totalPrice" type="Decimal" />
- Double: 定义一个double类型小数,通常可以被Decimal替代
- Integer:定义一个整数类型。eg:<aura:attribute name="numRecords" type="Integer" />
- Long:定义一个长整型类型,如果Integer盛装不了,需要使用Long。eg:aura:attribute name="numRecords" type="Long" />
- String:定义一个字符串类型。eg:<aura:attribute name="message" type="String" />
(注:上述基本类型也可以使用数组类型,eg:<aura:attribute name="message" type="String[]" />)
函数类型:与javascript类型相一致的attribute 类型。
对象类型:定义一个自定义的object或者sObject类型。eg:<aura:attribute name="acc" type="Account" />
集合类型:
- type[](Array):声明一个数组类型。eg:<aura:attribute name="colorPalette" type="String[]" default="['red','green', 'blue']" />
- List:声明一个有序列表(和type[]相似,个人认为此处可以替代type[])。eg: <aura:attribute name="colorPalette" type="List" default="['red', 'green', 'blue']" />
- Map:声明一个Map类型,包含键值对。eg:<aura:attribute name="testMap" type="Map" default="{a: 'label1', b:'label2' }" />
- Set:声明一个无序列表。eg:<aura:attriute name="colorSet" type="Set" default="{'red','green','blue'}" />
自定义Java类型:如果创建Java类型,这个类必须要实现JsonSerializable接口。
特定的Frame-work类型(Framework-Specific):
- Aura.Action:传递一个action到lightning:component中。eg: <aura:attribute name="onclick" type="Aura.Action"/>
<aura:registerEvent>: 通常用于创建完自定义event后,将event注册到component中,从而通过aura:handler将event进行装载。event包含系统自带的标准事件(init/change等)以及自定义事件,aura:registerEvent用于注册自定义事件。
<aura:handler>: lightning中提供了一些标准和自定义事件,将事件装载到lightning component中需要使用aura:handler。标准的事件举例:init(lightning component初始化触发,相当于VF page中的构造函数或者action声明内容),change(某个aura:attribute改变自动触发)。aura:handler写法如下:
<aura:component>
<aura:attribute name="childAttr" type="String" />
<aura:handler name="change" value="{!v.childAttr}" action="{!c.onChildAttrChange}"/>
</aura:component>
上面的demo声明了一个针对childAttr的change事件,当childAttr更改以后,便会执行controller.js的onChildAttrChange方法。
(点击可查看event的Best Practice)
元素标签:
aura framework提供了大量的可以直接使用的元素标签用来开发,用户也可以通过slds样式更改成需要的样式。官方提供了很多可以直接使用的标签,以ui: / lightning: aura: 开头。元素标签的样式使用slds进行渲染,如果想查看某个元素标签样式或者想要更改相关的样式,可以先查看lightning design system中元素的渲染方式。元素标签可以包含几大类来汇总:
容器组件
lightning:accordion / lightning:accordionSection : 可折叠容器
lightning:card :卡牌装容器,用于展示一组信息
lightning:layout/lightning:layoutItem : Grid容器
lightning:tab/lightning:tabset : Tab标签
lightning:tile : 瓷砖模型,用于展示一条记录的相关信息
按钮组件
lightning:button: 普通按钮
lightning:buttonIcon:只有一个html icon的按钮
lightning:buttonMenu/lightning:menuItem: 一个drop-down 列表展示action
导航组件
lightning:breadcrumb/lightning:breadcrumbs: 展示当前操作记录的层级导航
lightning:tree: 树形结构
lightning:verticalNavigation: 垂直排列的链接列表
可视化组件
lightning:avatar: 对象的可视化表示 (一个图像)
lightning:badge:包含少量信息的文本块标签
lightning:datatable: 显示table布局
lightning:dynamicIcon: 动画效果icon
lightning:helptext: hover后提示信息效果
lightning:icon: 显示一个图标
lightning:pill: 展示一个显示X号的内容,可以显示或者不显示
lightning:progressBar: 展示一项操作的进程条
lightning:progressIndicator:进程指示器,显示进程线
lightning:spinner: 显示Loading图形
字段组件
lightning:combobox :提供一个用户输入的并且可以autocomplete的控件
lightning:dualListbox: 两个list间移动option。类似multi picklist效果
lightning:fileUpload : 提供上传文件的框
lightning:fileCard : 展示一系列的上传的文件
lightning:input: 默认展示输入框,根据type不同展示不同效果。
lightning:radioGroup:展示一组单选按钮
lightning:select:展示一个包含多个option的菜单
lightning:slider : 展示一个可以滑动效果指定范围的输入框
lightning:inputRichText: 富文本编辑器
lightning:textArea: textArea
格式化组件
以下标签都是只读的
lightning:formattedDateTime :格式化 data & time
lightning:formattedEmail :格式化 email
lightning:formattedLocation :使用经纬度格式化Location
lightning:formattedNumber :格式化数字
lightning:formattedPhone:格式化电话号码
lightning:formattedRichText:格式化富文本区域
lightning:formattedText:格式化字符串
lightning:formattedUrl:格式化URL
一个元素标签包含local ID,global ID。local id 作用域为当前的component,使用aura:id 属性来创建一个local id。aura:id不支持表达式,只支持普通的字符串值作为local id.
local id 理论上是唯一的,但是不强制唯一,比如一组checkbox元素标签,可以设置他们的local id是相同的。local id可以用于在javascript中通过local id获取到元素本身或者元素列表。
eg:<lightning:input type="string" aura:id = "name" value="testValue" />
controller或者helper中可以通过cmp.find("name")即可获取到 aura:id为name的元素(或者元素列表),如果不存在所要搜索的aura:id,则返回undefined.controller.js/helper.js中针对一个元素获取它的local id,可以通过cmp.getLocalId()方法获得。
Global id 很像classic中visualforce 元素组件中的id,运行时生成,并且是唯一的。
eg:<lightning:input type="string" id="name" value="testValue" />
global id可以用来区分不同元素的组件实例化或者用于debugging操作。针对一个组件元素获取它的global id,可以通过cmp.getGlobalId()获取。
三. Controller js介绍
因为component不允许写任何的js,即使类似onclick="alert(xxx);"这种js也是被禁止的,所以controller js部分作用是至关重要的。他管理着Component中所有的事件驱动操作。
这里假设我们在'showMyInfo' componet中有一个按钮名字是'Button1',绑定了一个'onclick'事件,onclick="{!c.handlerClick}".上面我们说过,针对元素组件引用attribute的值,使用v(v代表了view)。
当我们点击按钮或者触发了注册的事件后,会执行controller.js里面的方法,需要写{!c.functionName},其中c可以理解为 client-side controller,functionName为在controller.js中声明的方法名称。
当我们为一个component bundle新建一个Controller js时,我们会发现,每个Controller方法里面默认都有3个参数:
- cmp : 代表当前操作的action所在的component,这里指的是showMyInfo
- event:代表当前action操作所触发的事件,通过事件可以获取到当前事件所对应的元素;
- helper:helper代表当前的componet对应的helper.js,当然这个参数不是必须的,helper文件可以写js内容用来和后台server controller交互。当然,如果你想把和server controller交互的代码写在当前的controller js中,也是可以的。
cmp:我们通常用cmp可以获取和设置attribute值,通过cmp.get('v.attributeName')即可获取到lightning component中attribute名称为attributeName的值。通过cmp.set('v.attributeName','testAttributeValue')即可设置lightning componet中名称为attributeName的attribute的值为testAttributeValue.当然,cmp可不止获取设置attribute值这么简单,还可以通过cmp.getEvent('eventName')获取注册的事件等等。我们平时用的cmp比较多的功能就是这两个了。
event:event代表当前操作的事件,比如当上面的用户点击了按钮,可以通过event.getSource()获取到事件源Button1以及获取到事件源自身的属性等信息;可以获取到事件源的事件操作。
helper:helper代表了helper.js的实例化变量,你可以通过helper.helperMethod用来处理具体的逻辑,包括和后台交互;处理结果集;功能性的方法重用等等。因为有了helper,你的代码有了更好的可读性,可维护性以及可重用性。
下面通过几行简单的代码来了解cmp以及event的用法。
- var btnClicked = event.getSource();此行代码可以理解为获取到点击的button的dom element
- var btnMessage = btnClicked.get(''v.label"); 通过element的get方法可以获取到这个元素上面的属性值,获取属性值或者获取其他的组件中的元素信息,需要使用'v.'来获取;
- component.set("v.message", btnMessage); 更新component中名称为message的attribute值。
- controller中有可能有多个方法,每个方法之间使用‘,’分隔;最后一个方法不能有‘,’。
({
handleClick: function(component, event, helper) {
var btnClicked = event.getSource(); // the button
var btnMessage = btnClicked.get("v.label"); // the button's label
component.set("v.message", btnMessage); // update our message
},
handleClick2: function(component,event,helper) {
}
})
四 Helper js 介绍
如果是controller.js负责了component中的所有业务逻辑,那么helper js就承包了所有的业务细节处理或者公用的方法(显示隐藏loading等)。helper一般需要component这个参数,其他参数可以根据实际需要自动从controller.js获取以及传递。这里举例一个调用后台并对返回数据进行处理的例子。想要连接后台,需要准备以下的工作:
1.lightning component 的controller属性设置此component后台引用的controller,用法和classic用法相同;
2.controller(后台)方法需要为静态方法,并且需要添加@AuraEnabled注解。如果有classic经验的可以想一下remote action的后台要求,把@RemoteAction改成@AuraEnabled就好。
createItem: function(component, camping) {
var action = component.get("c.saveItem");
action.setParams({
"camping": camping
});
action.setCallback(this, function(response){
var state = response.getState();
if (state === "SUCCESS") {
var items = component.get("v.items");
items.push(response.getReturnValue());
component.set("v.items", items);
} else if(status == "INCOMPLETE") {
console.log('execute');
} else if(status == "ERROR") {
console.log('error');
}
});
$A.enqueueAction(action);
}
上述例子功能为后台调用saveItem方法,camping作为参数传递到后台,然后异步调用。调用成功后将这个item写入到前台的camping列表中。
其中有几点需要注意:
1.我们通常使用component.get('v.something')来调用前台的一些属性元素等,在这里使用component.get('c.backgroundMethod')可以调用到后台的方法;
2.通过setParam可以对方法设置参数,通过setCallBack可以对这个方法进行异步处理,我们通常会将这种调用后台的方法进行异步结果处理;
3.response的状态主要有三种:SUCCESS/INCOMPLETE/ERROR。建议方法中将三种情况都进行处理,比如INCOMPLETE展示遮罩,ERROR/SUCCESS进行相应的业务处理以及解除遮罩等;
4.需要将action放在队列里面,让他排队进行执行。$A为lightning中封装的一个global变量,除了enqueueAction方法外还有很多常用的方法,后面会有涉及,有兴趣的自行查看。
总结:此篇只是泛泛的对lightning componet常用的进行简单的介绍,并没有系统的介绍使用功能等,也没有demo进行整体的连接。有兴趣的可以自己查看文档或者trailhead等学习资料,后期将会写一些细节的使用。有错误的地方欢迎指出,有不懂的欢迎提问。