本篇可參看: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感興趣的能夠本身去玩。篇中有錯誤的歡迎指出,有問題歡迎留言。