Salesforce LWC學習(二十九) getRecordNotifyChange(LDS拓展加強篇)

本篇參考: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

https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_get_record_notifyapi

以前在aura以及lwc得文章中都有過介紹 LDS(Lightning Data Service)。簡而言之, LDS實現了記錄得跨組件共有,而且當前得記錄在跨組件中得版本相同,從而實現不一樣得組件展現當前記錄一樣得內容。在lwc中,有兩個部分自動實現了LDS。緩存

  • lightning-record-form/lightning-record-view-form/lightning-record-edit-form
  • 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方法處理邏輯。此種適用於如下的場景:

  • 用於 wire adapter不支持的object的數據處理,好比 Event / Task;
  • 用於user interface不支持的操做,好比 wire adapter提供了容許獲取列表數據的方法,可是無法設置相關的filter的邏輯,咱們就可使用apex在後臺去處理複雜的邏輯;
  • 去處理一個transactional邏輯,好比建立一條 account之後,還想建立一個默認的contact,這種使用 wire adapter沒法實現,只能使用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保證是最新的痛點,項目中可能會常常用到,不瞭解的小夥伴快去查看一下官方文檔。篇中有錯誤的歡迎指出,有不懂歡迎留言。

相關文章
相關標籤/搜索