本篇可参看:https://trailhead.salesforce.com/modules/lightning_data_service网络
Lightning中针对object的detail页面,一个lightning app可能包含了多个components,多个components不可避免的会对这个数据进行CRUD操做,若是咱们针对每一个component都在init操做时后台SQL进行查询,而后赋值给前台变量,进行CUD操做时,还要考虑其余component的数据是否要级联的改变,这种操做以及设计对于性能的影响仍是蛮大的,有什么好的方法能够作到一次搜索或者一次加载,全部的components都共用吗?这个时候,LDS或许能够是你想要的。app
lightning中,咱们使用 Lightning Data Service(LDS)去服务于数据层面,LDS 提供了对数据的访问。函数
LDS除了可让一个app的全部的component共用一个share的数据,这样一个更新之后,全部的component(model 为view)都会同步的刷新这个数据。还能够支持用户离线操做数据,当网络链接之后,用户对数据的操做则会进行同步。性能
LDS优势归纳来讲:测试
最小化的XMLHttpRequestsflex
数据只须要搜索一次。优化
跨 components 分享数据记录ui
当数据改变之后会建立通知。this
优势还有不少,当一个app 涉及到记录的简单的增删改查操做,使用LDS是一个最优的方式。spa
说了这么多LDS的优势,那LDS如何使用呢?其实只须要在component中引入 <force:recordData>标签便可。
一. <force:recordData>属性介绍
<force:recordData>标签包含如下的经常使用属性:
recordId : 指定哪条记录来加载,此字段为必须字段。
mode: 指定当前的模式,有 View和Edit两个值。若是针对当前component有update操做,则mode设置为Edit。此字段为必须字段
layoutType: 决定了哪一个layout用于加载, FULL/COMPACT。
fields: 决定哪些字段用来搜索出来
layoutType以及fields至少有一个要求必须,由于管理员拥有更改pagelayout的权限,因此layoutType加载的字段具备不肯定性,推荐使用fields。
targetRecord: 此属性至关于这条记录ID对应的记录变量,经过此变量能够访问fields中指定的字段值。
targetFields: targetRecord对应的字段的视图,经过此字段能够取出fields中的指定的值。
经过上面的描述能够看出来targetRecord以及targetFields都可以取出fields中指定的字段值,他们两个写法尽管不一样,可是他们的表达含义以及取得值相同,后面有具体的描述。
targetError: 此属性存储Error Message, 若是记录没有正确的提供。
recordUpdated:此属性指定当记录进行了CUD操做时的事件处理。
简单Demo以下:其中 {v.accountFields.Name} 等同于{!v.record.fields.Name}.
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId"> <aura:attribute name="record" type="Object"/> <aura:attribute name="accountException" type="String"/> <aura:attribute name="accountFields" type="Object"/> <force:recordData recordId="{!v.recordId}" aura:id="accId" targetRecord="{!v.record}" targetFields="{!v.accountFields}" targetError="{!v.accountException}" fields="Id,Name,Industry" mode="VIEW"/> <lightning:card title="{!v.accountFields.Name}"> <lightning:formattedText title="Industry" value="{!v.record.fields.Industry}"/> </lightning:card> </aura:component>
二. LDS的 CUD,错误提示以及自带的事件监听操做
force:recordData组件元素自带了好几个方法用来实现数据的简单的增删改操做。controller.js中经过获取到force:recordData元素后调用相关的方法便可进行DML操做。经常使用方法以下:
经过上面的经常使用的三个方法,咱们会关注到SaveRecordResult这个对象,此类做为CUD操做的callback返回的惟一参数,此对象具备如下的字段:
getNewRecord():此方法用于建立一个空的记录,方法有四个参数:
saveRecord():此方法用于create/edit操做,方法只有一个参数:
deleteRecord():此方法用于delete操做,方法也只有一个参数:
上面说过,经过LDS能够在数据变化后,共用的component实时的刷新数据,可是当两个一样的字段同时在Edit 模式下,则不会同时刷新,即刷新数据仅限于View模式下。
举个例子:Account 新增一个 Action,用来展现和更新Account的部分字段信息。
1). accDisplay.cmp : 用来展现主要的几个字段
1 <aura:component implements="flexipage:availableForRecordHome,force:hasRecordId"> 2 <aura:attribute name="record" type="Object"/> 3 <aura:attribute name="accountException" type="String"/> 4 <aura:attribute name="recordFields" type="Object"/> 5 <force:recordData 6 recordId="{!v.recordId}" 7 aura:id="accId" 8 targetRecord="{!v.record}" 9 targetFields="{!v.recordFields}" 10 fields="Name,AccountNumber,Site" 11 mode="VIEW" 12 /> 13 <lightning:card title="Acc View" iconName="action:info"> 14 <lightning:formattedText title="Name" value="{!v.recordFields.Name}"/> 15 <br/> 16 <lightning:formattedText title="Account Number" value="{!v.recordFields.AccountNumber}"/> 17 <br/> 18 <lightning:formattedText title="Site" value="{!v.recordFields.Site}"/> 19 <br/> 20 21 </lightning:card> 22 </aura:component>
2). accEdit2.cmp:更新固定的几个字段
1 <aura:component implements="force:hasRecordId, 2 force:lightningQuickActionWithoutHeader"> 3 <aura:attribute name="record" 4 type="Object" description="current record reference"/> 5 <aura:attribute name="recordFields" 6 type="Object" description="current record fields list"/> 7 <aura:attribute name="recordError" 8 type="String" description="if error occurs,record error reference"/> 9 10 <force:recordData aura:id="editRecordId" 11 fields="Name,AccountNumber,Site" 12 recordId="{!v.recordId}" 13 targetError="{!v.recordError}" 14 targetRecord="{!v.record}" 15 targetFields="{!v.recordFields}" 16 mode="EDIT" 17 /> 18 19 <!-- Display an editing form --> 20 <div class="Edit Account Details"> 21 <lightning:card iconName="action:edit" title="{!v.recordFields.Name}"> 22 <div class="slds-p-horizontal--small"> 23 24 <lightning:input label="Name" 25 value="{!v.recordFields.Name}"/> 26 <br/> 27 <lightning:input label="Account Number" 28 value="{!v.recordFields.AccountNumber}"/> 29 <br/> 30 <lightning:input label="Site" 31 value="{!v.recordFields.Site}"/> 32 <br/> 33 34 <lightning:button label="Save" 35 variant="brand" 36 onclick="{!c.handleSaveRecord}"/> 37 </div> 38 </lightning:card> 39 </div> 40 41 <!-- if error occurs, display operate error --> 42 <aura:if isTrue="{!not(empty(v.recordError))}"> 43 <div class="recordError"> 44 {!v.recordError} 45 </div> 46 </aura:if> 47 </aura:component>
3). AccComponent.cmp: 经过Tab方式展现数据信息,由于想要测试一个场景,因此此component里面引用了两遍accEdit2.cmp
1 <aura:component implements="flexipage:availableForAllPageTypes,force:lightningQuickAction,force:hasRecordId"> 2 <lightning:tabSet class="slds-tabs_scoped"> 3 <lightning:tab label="Acc View"> 4 <c:AccDisplay recordId="{!v.recordId}"/> 5 </lightning:tab> 6 <lightning:tab label="Acc Edit"> 7 <c:AccEdit2 recordId="{!v.recordId}"/> 8 </lightning:tab> 9 <lightning:tab label="Acc Edit2"> 10 <c:AccEdit2 recordId="{!v.recordId}"/> 11 </lightning:tab> 12 </lightning:tabSet> 13 </aura:component>
4). 新建一个Lightning Action,而且将此Action放在Page Layout中
结果展现:
1.点击Edit Test会弹出Pop Up Window
2.在ACC EDIT Tab输入了内容点击Save之后,结果展现位ACC View的Tab会马上显示输入后save的内容,而ACC Edit2 Tab则会保留原值。
经过结果能够看出来,在mode为view状况下,save之后会马上显示在view视图中。在mode为Edit状况下,若是edit1有某个字段更新,好比Account Number,则edit2的Account Number不会被更新。这种设计也是正常的,由于若是同步更新会有歧义,可是咱们有一些场景仍是但愿Edit模式下也能够自动更新这些值得,这个时候就可使用到自带的事件监听。
自带事件监听使用很是简单,只须要<force:recordData>标签增长属性:recordUpdated属性设置你须要后台controller绑定的handler便可。
使用LDS的事件监听有4中类型: CHANGED / LOADED / REMOVED / ERROR。 从名字能够看出来分别对应着 更改 / 加载 / 移除 / 错误。
下面咱们针对上面的程序进行改进,对accEdit2.cmp 优化一下force:recordData组件元素
1 <force:recordData aura:id="editRecord2Id" 2 fields="Name,AccountNumber,Site" 3 recordId="{!v.recordId}" 4 targetError="{!v.recordError}" 5 targetRecord="{!v.record}" 6 targetFields="{!v.recordFields}" 7 mode="EDIT" 8 recordUpdated="{!c.reloadUpdate}" 9 />
对accEdit2Controller.js增长一个reloadUpdate方法,其中调用reloadRecord()方法能够对force:recordData进行从新数据加载。
1 reloadUpdate : function(component, event, helper) { 2 var eventParams = event.getParams(); 3 if(eventParams.changeType == "CHANGED") { 4 // get the changed fields for this record 5 var changedFields = eventParams.changedFields; 6 console.log('Chaged Fields: ' + JSON.stringify(changedFields)); 7 component.find('editRecordId').reloadRecord(); 8 } else if(eventParams.changeType === "LOADED") { 9 console.log("Record is loaded successfully."); 10 } else if(eventParams.changeType === "REMOVED") { 11 var deleteRecordResult = $A.get("e.force:showToast"); 12 deleteRecordResult.setParams({ 13 "title": "Delete Result", 14 "message": "The record was deleted." 15 }); 16 deleteRecordResult.fire(); 17 } else if(eventParams.changeType === "ERROR") { 18 console.log('Error: ' + component.get("v.error")); 19 } 20 }
加强上述方法之后,在从新运行,当ACC Edit Tab中改了相关的值之后,ACC Edit2 Tab的值也会同步的更新,由于LDS已经加载成了最新的值。
(注意:调用reloadRecord()方法之后,会从新执行事件类型为LOADED的事件设置,demo中若是save之后会打出Record is loaded successfully.)
总结:使用LDS能够在不使用controller状况下便进行简单的CUD操做,很相似classic 中的standcontroller功能。这种方式在lightning中仍是很常见的,可是若是涉及到复杂的数据关联的改动或者transaction中须要进行屡次更新操做,建议不使用LDS换成后台controller中去作。篇中只弄了Edit的demo,new以及delete的demo感兴趣的能够本身去玩。篇中有错误的欢迎指出,有问题欢迎留言。