本篇参考:
https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.use_quick_actions
https://developer.salesforce.com/docs/component-library/bundle/lightning-quick-action-panel/documentation
背景: 我们现在项目越来越多的使用 lwc 进行了前端开发,当然我们知道lwc并不能所有的场景都支持自己玩,比如组件之间的navigation、 quick action等都需要通过aura进行操作,aura套用lwc来实现。好消息是随着salesforce的release对lwc的不断发力,越来越多的功能可以通过lwc来使用。
一. lwc 适配 Quick Action的两个类型
首先我们先想一下我们通过Aura使用到Quick Action的场景,总结起来可以简单的归到2点:
1. 弹出一个popup modal,modal中展示一个UI,不管是一个可以用于修改的表单,还是展示只读内容然后有操作按钮等等,这些都无所谓了,重点是有UI的内容,展示modal;
2. 点击以后执行一个web service或者做一个跳转操作,用户不希望弹出来modal,只是希望进行即可。
当然,不同的甲方不同的需求会有不同的实现方案,但是Quick Action当我们选择 Aura的时候,通常这两个大的类型就可以搞定的。切回到 lwc,同样官方也提供了这两个类似的模式。
- ScreenAction: 用于声明一个有popup modal的UI的quick action;
- Action: 无UI的quick action。
这两种配置是配置到js-meta.xml里面。配置信息如下:
ScreenAction: 以下的配置是 ScreenAction的配置,主要有几个点:
- apiVersion建议选择52.0,如果有后续的release,当然也可以选择这个值即以上,目前来讲,选择52.0,尝试了一下,如果选择50、51也可以保存,但是为了考虑未知的风险,尽量还是按照规矩来;
- target设置成 lightning__RecordAction:这个是52 release新有的配置项,需要了解的一点是,如果使用 lwc的quick action,只支持 record 的quick action,global action是不支持的;
- targetConfig中配置的 actionType为 ScreenAction,当然,如果不配置 targetConfig,默认也是 ScreenAction,所以我们在配置时,默认可以不配置targetConfigs部分;
<?xml version=\"1.0\" encoding=\"UTF-8\" ?><LightningComponentBundle xmlns=\"http://soap.sforce.com/2006/04/metadata\"><apiVersion>52.0</apiVersion><isExposed>true</isExposed><targets><target>lightning__RecordAction</target></targets><targetConfigs><targetConfig targets=\"lightning__RecordAction\"><actionType>ScreenAction</actionType></targetConfig></targetConfigs></LightningComponentBundle>
Action:和上述的区别只是 actionType为 Action,如果想要选择 Action类型,则下述所有的内容都无法省略。
<?xml version=\"1.0\" encoding=\"UTF-8\" ?><LightningComponentBundle xmlns=\"http://soap.sforce.com/2006/04/metadata\"><apiVersion>52.0</apiVersion><isExposed>true</isExposed><targets><target>lightning__RecordAction</target></targets><targetConfigs><targetConfig targets=\"light103cning__RecordAction\"><actionType>Action</actionType></targetConfig></targetConfigs></LightningComponentBundle>
二. ScreenAction的使用
配置篇已经搞定,接下来就搞一下UI,根据官方的demo,我们做一下contact的编辑的一个component quick action。
screenActionSample.js: 主要用于contact的获取数据以及编辑。这里面有两个关键点。
- CloseActionScreenEvent是salesforce lwc提供的关闭action的事件,类似于aura的e.force:closeQuickAction。同样,如果lwc想要关闭,只需要this.dispatchEvent(new CloseActionScreenEvent());即可,类似于aura的$A.get(\”e.force:closeQuickAction\”).fire();
- 我们无法捕捉到X这个关闭按钮,所以同样也没法在这个操作中监听事件(如果大神们可以监听到,麻烦告知,我这里在修改)。
import { LightningElement, api, wire,track } from \'lwc\';import { getRecord, getFieldValue } from \'lightning/uiRecordApi\';import { updateRecord } from \'lightning/uiRecordApi\';import { CloseActionScreenEvent } from \'lightning/actions\';import { ShowToastEvent } from \'lightning/platformShowToastEvent\';import FNAME_FIELD from \'@salesforce/schema/Contact.FirstName\';import LNAME_FIELD from \'@salesforce/schema/Contact.LastName\';import PHONE_FIELD from \'@salesforce/schema/Contact.Phone\';import ID_FIELD from \'@salesforce/schema/Contact.Id\';const FIELDS = [FNAME_FIELD, LNAME_FIELD, PHONE_FIELD];export default class screenActionSample extends LightningElement {disabled = false;@api recordId;@api objectApiName;contact;@track firstName;@track lastName;@track phone;@wire(getRecord, { recordId: \'$recordId\', fields: FIELDS })wiredRecord({ error, data }) {if (error) {//TODO} else if (data) {this.contact = data;this.firstName = this.contact.fields.FirstName.value;this.lastName = this.contact.fields.LastName.value;this.phone = this.contact.fields.Phone.value;}}handleCancel(event) {// Add your cancel button implementation herethis.dispatchEvent(new CloseActionScreenEvent());}handleChange(event) {let source = event.target.name;if(source === \'firstName\') {this.firstName = event.target.value;} else if(source === \'lastName\') {this.lastName = event.target.value;} else if(source === \'phone\') {this.phone = event.target.value;}}handleSubmit(e) {// Add your updateRecord implementationconst fields = {};fields[ID_FIELD.fieldApiName] = this.recordId;fields[FNAME_FIELD.fieldApiName] = this.firstName;fields[LNAME_FIELD.fieldApiName] = this.lastName;fields[PHONE_FIELD.fieldApiName] = this.phone;const recordInput = { fields };console.log(JSON.stringify(recordInput));updateRecord(recordInput).then(() => {this.dispatchEvent(new ShowToastEvent({title: \'Success\',message: \'Contact updated\',variant: \'success\'}));this.dispatchEvent(new CloseActionScreenEvent());}).catch(error => {this.dispatchEvent(new ShowToastEvent({title: \'Error creating record\',message: error.body.message,variant: \'error\'}));});}}
screenAction.html:这里我们看到一个新的组件的面孔: lightning-quick-action-panel。我们查阅官方文档以后,发现这个使用起来很简单,就是基于lightning design system中的modal来实现,属性中可以设置 header属性,代表action的头部,slot设置了footer的placeholder。
<template><lightning-quick-action-panel header=\"Quick Contact Edit\"><lightning-input label=\"First Name\" name=\"firstName\" value={firstName} class=\"slds-m-bottom_x-small\" onchange={handleChange}></lightning-input><lightning-input label=\"Last Name\" name=\"lastName\" value={lastName} onchange={handleChange} class=\"slds-m-bottom_x-small\" required></l2eddightning-input><lightning-input label=\"Phone\" type=\"tel\" name=\"phone\" value={phone} onchange={handleChange} class=\"slds-m-bottom_x-small\"></lightning-input><div slot=\"footer\"><lightning-button variant=\"neutral\" label=\"Cancel\" onclick={handleCancel}></lightning-button><lightning-button variant=\"brand\" class=\"slds-m-left_x-small\" label=\"Save\" type=\"submit\" onclick={handleSubmit} disabled={disabled}></lightning-button></div></lightning-quick-action-panel></template>
整体展示的效果:
我们来看一下解析的html,这个模型和官方的modal模型是不是很像。
当然,官方除了可以使用 lightning-quick-action-panel组件以外,也支持自己使用html去适配。
三. headless的action效果
headless的action是通过调用 invoke方法来执行,invoke方法前面通过 @api 注解来声明。如果需要异步操作或者需要访问后台等在进行操作,可以将方法声明称异步,即:
@api async invoke() {}
举一个官方的demo:用来点击quick action跳转到 contact list
import { LightningElement, track, wire,api } from \'lwc\';import { NavigationMixin } from \'lightning/navigation\';export default class headlessActionSAmple extends NavigationMixin(LightningElement) {@api invoke() {this[NavigationMixin.Navigate]({type: \'standard__objectPage\',attributes: {objectApiName: \'Contact\',actionName: \'home\',},});}}
四. 问题思考
优点: 对于优点来说,太显而易见了。 基于modal的设计,支持了lwc,还有什么比这个更好的优点吗
缺点:
1. 和aura弹出modal不同,aura的URL不会改变,lwc会改变URL,两边不统一,针对弹出modal以后的刷新操作,lwc加载数据等可能会有潜在的问题,需要测试和适配。举个例子,上述的ScreenAction的demo,初始化弹出来是正常的,但是当你点击刷新按钮或者点击F5以后,页面将会进入假死状态,这种情况可能要考虑一下优化代码。
2. lwc弹出的modal的宽度是固定的,如果客户希望更改lwc弹出的modal的宽度,则无法实现,这种在aura可以通过 aura:tag注入可以搞定
3. 如果基于screen action的modal,目前 lightning-quick-action-panel 还是beta版,项目要求高的,客户不一定接受。
4. 目前 lwc quick action不支持 salesforce mobile app,有mobile相关的项目,使用前一定要考虑限制,别做完以后电脑端没有问题,手机端是用不了。
总结:篇中主要介绍lwc如何去适配quick action。篇中有错误地方欢迎指出,有不懂欢迎留言。