本篇參考:javascript
https://developer.salesforce.com/docs/component-library/documentation/en/lwc/data_ui_apihtml
https://developer.salesforce.com/docs/component-library/documentation/en/lwc/data_guidelinesjava
以前在aura以及lwc得文章中都有過介紹 LDS(Lightning Data Service)。簡而言之, LDS實現了記錄得跨組件共有,而且當前得記錄在跨組件中得版本相同,從而實現不一樣得組件展現當前記錄一樣得內容。在lwc中,有兩個部分自動實現了LDS。緩存
lightning/ui*Api模塊中得全部得wire adapter得方法。
這樣說來很懵,舉個例子更直觀得理解。異步
RecordNotifyChangeController.clsasync
1 public with sharing class RecordNotifyChangeController { 2 @AuraEnabled 3 public static String saveAccount(String recordId,String industry,String phone) { 4 Account accountItem = new Account(); 5 accountItem.Id = recordId; 6 accountItem.industry = industry; 7 accountItem.phone = phone; 8 accountItem.Name = industry + phone; 9 try { 10 update accountItem; 11 return 'success'; 12 } catch(Exception e) { 13 return 'error'; 14 } 15 } 16 17 @AuraEnabled(cacheable=true) 18 public static Account getAccount(String recordId) { 19 Account accountItem = [SELECT Name,Industry,Phone from Account where Id = :recordId limit 1]; 20 return accountItem; 21 } 22 }
recordNotifyChangeSample.jside
1 import { LightningElement, wire,api,track } from 'lwc'; 2 import { getRecord } from 'lightning/uiRecordApi'; 3 import { refreshApex } from '@salesforce/apex'; 4 import saveAccount from '@salesforce/apex/RecordNotifyChangeController.saveAccount'; 5 import getAccount from '@salesforce/apex/RecordNotifyChangeController.getAccount'; 6 import PHONE_FIELD from '@salesforce/schema/Account.Phone'; 7 import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry'; 8 import NAME_FIELD from '@salesforce/schema/Account.Name'; 9 export default class RecordNotifyChangeSample extends LightningElement { 10 @api recordId; 11 12 @track phone; 13 14 @track industry; 15 16 @track accountName; 17 18 fields=[PHONE_FIELD,INDUSTRY_FIELD]; 19 20 accountRecord; 21 22 // Wire a record. 23 @wire(getRecord, { recordId: '$recordId', fields: [PHONE_FIELD, INDUSTRY_FIELD,NAME_FIELD]}) 24 wiredAccount(value) { 25 this.accountRecord = value; 26 const { data, error } = value; 27 if(data && data.fields) { 28 this.industry = data.fields.Industry.value; 29 this.phone = data.fields.Phone.value; 30 this.accountName = data.fields.Name.value; 31 } else if(error) { 32 //TODO 33 } 34 } 35 36 37 handleChange(event) { 38 if(event.target.name === 'phone') { 39 this.phone = event.detail.value; 40 } else if(event.target.name === 'industry') { 41 this.industry = event.detail.value; 42 } 43 } 44 45 handleSave() { 46 saveAccount({ recordId: this.recordId, industry : this.industry, phone : this.phone}) 47 .then(result => { 48 if(result === 'success') { 49 refreshApex(this.accountRecord); 50 } else { 51 //TODO 52 } 53 }) 54 .catch(error => { 55 //TODO 56 }); 57 } 58 59 }
recordNotifyChangeSample.html函數
1 <template> 2 <lightning-card title="use lightning-record-form"> 3 <lightning-record-form object-api-name="Account" fields={fields} record-id={recordId} mode="view"></lightning-record-form> 4 </lightning-card> 5 6 <lightning-card title="use lightning input"> 7 <lightning-layout multiple-rows="true"> 8 <lightning-layout-item size="12"> 9 <lightning-input value={accountName} label="Name"></lightning-input> 10 </lightning-layout-item> 11 <lightning-layout-item size="6"> 12 <lightning-input value={phone} label="Phone" name="phone" onchange={handleChange}></lightning-input> 13 </lightning-layout-item> 14 <lightning-layout-item size="6"> 15 <lightning-input value={industry} name="industry" label="Industry"></lightning-input> 16 </lightning-layout-item> 17 <lightning-layout-item size="12"> 18 <lightning-button onclick={handleSave} label="save"></lightning-button> 19 </lightning-layout-item> 20 </lightning-layout> 21 </lightning-card> 22 </template>
效果展現:ui
1. 下方頁面由幾部分組成,由於在lightning中,一個頁面可能包含多個組件,多個組件可能共用數據,使用LDS得好處是全部得緩存都是同一個版本,即一個修改改變了version之後,全部的使用當前LDS的都從新刷新版本到最新,展現最新的內容。
2. 咱們使用 inline edit更改industry的值,更改之後不用刷新當前頁面,上面的兩部分引用內容會自動改變。
LDS雖然用的爽,可是畢竟有限制,由於只有知足上面所說的條件才能夠共用LDS的緩存,若是使用 @wire調用後臺apex的代碼則沒法實現 共用LDS從而致使一個頁面各個 component展現出現問題。說到這裏提一下在lwc中 work with data一般的使用順序。
1. 若是需求可使用 lightning-record-form / lightning-record-view-form / lightning-record-edit-form場景,優先使用。使用此種標籤須要考慮權限問題,由於使用此標籤權限取決於當前的 user對當前的表和字段訪問權限。若是咱們對這個表和字段沒有相關的權限,就無法正常的使用。並且 這三個標籤不是針對全部的表都有效,使用時須要查看你的表是否支持,好比 Event/Task就不支持。並且這三個表不適用於特別複雜的新建/更新場景。
2. 若是需求使用1所述內容沒法實現,可使用 lwc提供的相關的 wire adapter的方法,好比 getRecord,updateRecord等。此種仍是針對大部分standard object以及全部custom object有效,會比1更靈活處理。
3. 使用wire 或者命令式調用apex方法處理邏輯。此種適用於如下的場景:
apex方法好用是好用,由於能搞定任何的場景,可是他有一個缺點,即查詢的數據不是LDS,若是數據進行了更新,本頁面其餘的component若是引用了LDS,數據的版本不是最新的版本,則展現了不一樣步的數據現象。舉例說明,咱們對 上面demo中的wiredAccount從getRecord方法換成後臺 經過apex獲取數據。
recordNotifyChangeSample.js
1 import { LightningElement, wire,api,track } from 'lwc'; 2 import { getRecord } from 'lightning/uiRecordApi'; 3 import { refreshApex } from '@salesforce/apex'; 4 import saveAccount from '@salesforce/apex/RecordNotifyChangeController.saveAccount'; 5 import getAccount from '@salesforce/apex/RecordNotifyChangeController.getAccount'; 6 import PHONE_FIELD from '@salesforce/schema/Account.Phone'; 7 import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry'; 8 import NAME_FIELD from '@salesforce/schema/Account.Name'; 9 export default class RecordNotifyChangeSample extends LightningElement { 10 @api recordId; 11 12 @track phone; 13 14 @track industry; 15 16 @track accountName; 17 18 fields=[PHONE_FIELD,INDUSTRY_FIELD]; 19 20 accountRecord; 21 22 @wire(getAccount,{recordId : '$recordId'}) 23 wiredAccount(value) { 24 this.accountRecord = value; 25 const { data, error } = value; 26 if(data) { 27 this.industry = data.Industry; 28 this.phone = data.Phone; 29 this.accountName = data.Name; 30 } 31 } 32 33 34 handleChange(event) { 35 if(event.target.name === 'phone') { 36 this.phone = event.detail.value; 37 } else if(event.target.name === 'industry') { 38 this.industry = event.detail.value; 39 } 40 } 41 42 handleSave() { 43 saveAccount({ recordId: this.recordId, industry : this.industry, phone : this.phone}) 44 .then(result => { 45 if(result === 'success') { 46 refreshApex(this.accountRecord); 47 } else { 48 //TODO 49 } 50 }) 51 .catch(error => { 52 //TODO 53 }); 54 } 55 56 }
結果展現
這種就會充滿了困惑,同一個頁面相同記錄數據展現兩個version,天然用戶這關過不了。如何解決呢?下面就講一下今天的主角:getRecordNotifyChange。
getRecordNotifyChange用於查詢指定的記錄ID或ID列表,將他們的LDS的緩存和version刷新到最新。從而實現apex調用狀況下,即便在更新了數據狀況下,整個頁面的LDS都是最新的。須要注意的是,這個 功能僅用於 version 50及以上版本,若是是48/49或者其餘的老版本不支持。具體使用直接上demo
1 import { LightningElement, wire,api,track } from 'lwc'; 2 import { getRecord,getRecordNotifyChange } from 'lightning/uiRecordApi'; 3 import { refreshApex } from '@salesforce/apex'; 4 import saveAccount from '@salesforce/apex/RecordNotifyChangeController.saveAccount'; 5 import getAccount from '@salesforce/apex/RecordNotifyChangeController.getAccount'; 6 import PHONE_FIELD from '@salesforce/schema/Account.Phone'; 7 import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry'; 8 import NAME_FIELD from '@salesforce/schema/Account.Name'; 9 export default class RecordNotifyChangeSample extends LightningElement { 10 @api recordId; 11 12 @track phone; 13 14 @track industry; 15 16 @track accountName; 17 18 fields=[PHONE_FIELD,INDUSTRY_FIELD]; 19 20 accountRecord; 21 22 @wire(getAccount,{recordId : '$recordId'}) 23 wiredAccount(value) { 24 this.accountRecord = value; 25 const { data, error } = value; 26 if(data) { 27 this.industry = data.Industry; 28 this.phone = data.Phone; 29 this.accountName = data.Name; 30 } 31 } 32 33 34 handleChange(event) { 35 if(event.target.name === 'phone') { 36 this.phone = event.detail.value; 37 } else if(event.target.name === 'industry') { 38 this.industry = event.detail.value; 39 } 40 } 41 42 async handleSave() { 43 await saveAccount({ recordId: this.recordId, industry : this.industry, phone : this.phone}) 44 .then(result => { 45 if(result === 'success') { 46 refreshApex(this.accountRecord); 47 getRecordNotifyChange([{recordId: this.recordId}]); 48 } else { 49 //TODO 50 } 51 }) 52 .catch(error => { 53 //TODO 54 }); 55 } 56 57 }
上面demo中主要改了兩部分:
1. 在頭部引入了 getRecordNotifyChange
2. handleSave須要使用 async或者 Promise,demo中使用異步操做。這個是硬性要求。
結果展現:
總結:getRecordNotifyChange實現了使用調用後臺apex狀況下,LDS保證是最新的痛點,項目中可能會常常用到,不瞭解的小夥伴快去查看一下官方文檔。篇中有錯誤的歡迎指出,有不懂歡迎留言。