引入本篇知识以前,我们先思考一个问题。Lightning中针对数据的详情页面,一个页面可能包含了多个components针对当前表的字段展示和编辑,我们是不可能针对每一个组件都进行搜索,然后显示或者编辑的。因为如果我们针对每个component都在init操作时后台SQL进行查询,然后赋值给前台变量,进行CUD操作时,还要考虑其他component的数据是否要级联的改变,这种操作以及设计对于性能的影响还是蛮大的,有什么好的方法可以做到一次搜索或者一次加载,所有的components都共用当前的缓存内容吗?这个时候,LDS或许可以是你想要的。
在Lightning Data Service(LDS)中加载的记录被缓存并在各组件间共享。如果一个页面由显示相同记录的组件组成,所有组件都显示相同版本的记录。访问同一记录的组件可以看到显著的性能改善,因为一个记录只被加载一次,无论有多少组件在使用它。这里说的只是一个概念,大家可能好奇我使用什么组件或者什么行为,系统会认为你当前使用的是LDS,可以享受相同缓存的内容。官方针对LDS目前由两部分构成。
lightning/ui*Api
下的所有的wire adapter方法,主要功能是对表数据的CRUD,对表指定视图列表数据获取,获取表schema信息等。我们以项目中常用的几个进行简单描述,其他的可以查看官方文档:https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_ui_api
getRecord:使用这个wire adapter用来获取一条记录信息
使用getRecord这个wire adapter,需要遵循以下的步骤:
头部引入getRecord →import { getRecord } from 'lightning/uiRecordApi';
使用 wire注解,头部需要引入wire。import { LightningElement,wire
} from 'lwc';基于以下的两种语句格式进行获取,其中 recordId必填, fields / layoutTypes其中有一个必填并且只需要一个属性,不同时用。
@wire(getRecord, { recordId: string, fields: string|string[], optionalFields?: string|string[] })
propertyOrFunction
@wire(getRecord, { recordId: string, layoutTypes: string|string[],
modes?: string|string[], optionalFields?: string|string[] })
propertyOrFunction
getFieldValue:在基于getRecord情况下返回指定字段的值。当我们使用 getRecord时,返回结果的结构为:record.data.fields.fieldName.value
,可以直接调用getFieldValue(record, field)
获取字段值。
createRecord:使用此wire adapter创建一条记录。
updateRecord:使用此wire adapter修改一条记录。
deleteRecord:使用此wire adapter删除一条记录。
我们以一个例子融合一下LDS的两种方式来看一下公用缓存的效果。
myComponentWithViewRecord.html:使用 lightning-record-form实现Account表的查看的组件
<template>
<lightning-record-form
record-id={recordId}
object-api-name="Account"
layout-type="Compact"
mode="view">
</lightning-record-form>
</template>
myComponentWithViewRecord.js
import { LightningElement, api, wire } from 'lwc';
export default class myComponentWithViewRecord extends LightningElement {
@api recordId;
}
myComponentWithRecordEdit.html:使用 lightning-record-form实现Account表的编辑的组件
<template>
<lightning-record-form
record-id={recordId}
object-api-name={objectApiName}
fields={fields}
columns="2"
mode="edit"
onsubmit={handleSubmit}
onsuccess={handleSuccess}
onerror={handleError}
oncancel={handleCancel}
onload={handleLoad}
>
</lightning-record-form>
</template>
MyComponentWithRecordEdit.js
/* eslint-disable no-console */
import { LightningElement, api } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import NAME_FIELD from '@salesforce/schema/Account.Name';
import REVENUE_FIELD from '@salesforce/schema/Account.AnnualRevenue';
import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry';
export default class MyComponentWithRecordEdit extends LightningElement {
// The record page provides recordId and objectApiName
@api recordId;
@api objectApiName;
fields = [NAME_FIELD, REVENUE_FIELD, INDUSTRY_FIELD];
handleLoad(event) {
console.log('execute handle load');
}
handleSubmit(event){
console.log('execute handle submit');
event.preventDefault(); // stop the form from submitting
const fields = event.detail.fields;
fields.LastName = 'My Custom Last Name'; // modify a field
this.template.querySelector('lightning-record-form').submit(fields);
}
handleSuccess(event) {
console.log('execute handle success');
const evt = new ShowToastEvent({
title: "Account Operated",
message: "Record ID: " + event.detail.id,
variant: "success"
});
this.dispatchEvent(evt);
}
handleError(event) {
console.log('execute handle error');
const evt = new ShowToastEvent({
title: "Account Operated",
message: event.detail.message,
variant: "error"
});
this.dispatchEvent(evt);
}
handleCancel(event) {
console.log('execute handle cancel')
const evt = new ShowToastEvent({
title: "Account canceled",
variant: "cancel"
});
this.dispatchEvent(evt);
}
}
myComponentWithRecordView.html:使用lightning-record-view-form实现Account表的查看的组件
<template>
<lightning-record-view-form
record-id={recordId}
object-api-name="Account">
<div class="slds-grid">
<div class="slds-col">
<lightning-output-field field-name="Name"></lightning-output-field>
</div>
<div class="slds-col">
<lightning-output-field field-name="Phone"></lightning-output-field>
</div>
<div class="slds-col">
<lightning-output-field field-name="AnnualRevenue"></lightning-output-field>
</div>
<div class="slds-col">
<lightning-output-field field-name="Industry"></lightning-output-field>
</div>
</div>
</lightning-record-view-form>
</template>
myComponentWithRecordView.js
import { LightningElement, api, wire } from 'lwc';
export default class myComponentWithRecordView extends LightningElement {
@api recordId;
}
myComponentWithEditRecord.html:使用lightning-record-edit-form实现Account表的编辑的组件
<template>
<lightning-record-edit-form
record-id={recordId}
object-api-name={objectApiName}
onsubmit={handleSubmit}
onload={handleLoad}
onsuccess={handleSuccess}
onerror={handleError}
>
<lightning-messages></lightning-messages>
<lightning-input-field field-name="Name"></lightning-input-field>
<lightning-input-field field-name="Industry"></lightning-input-field>
<lightning-input-field field-name="AnnualRevenue"></lightning-input-field>
<div class="slds-m-top_medium">
<lightning-button class="slds-m-top_small" label="Cancel" onclick={handleReset}></lightning-button>
<lightning-button class="slds-m-top_small" type="submit" label="Save Record"></lightning-button>
</div>
</lightning-record-edit-form>
</template>