本篇參考:
https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.use_quick_actions
背景: 我們現在項目越來越多的使用 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="lightning__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 here this.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 implementation const 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></lightning-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。篇中有錯誤地方歡迎指出,有不懂歡迎留言。