Salesforce LWC 组件间通信

Salesforce LWC 组件间通信

LWC组件间通信,通常是父子组件通信和非父子组件通信,一般有三种场景:

  • 父组件向子组件传递值。一般在子组件的变量或方法使用@api注解,由父组件向@api公开的变量传递值,或调用子组件方法。
  • 子组件向父组件传递值。一般使用CustomEvent,子组件通过dispatchEvent发出一个事件,由父组件监听。
  • 非父子组件传递值。一般使用LMS(Lightning Message Service),这是一种发布订阅模式,由发布者发布event,再由订阅者订阅,接收payload。

一、父子组件传值

1.1 父组件向子组件传递值

第一,子组件中使用@api公开变量(方法)即可。

sonLwc.js

scala 复制代码
 import { LightningElement, api } from 'lwc';
 import LightningAlert from 'lightning/alert';
 ​
 export default class SonLwc extends LightningElement {
     @api itemName = 'Test';
 ​
     @api alertItemNameInfo() {
         LightningAlert.open({
             message: this.itemName,
             theme: 'info'
         });
     }
 }

第二,父组件调用子组件,通过c-的方式引用子组件,公开的变量也使用同样的方式去传递值。

parentLwc.html

xml 复制代码
 <template>
     <lightning-card title="Parent LWC" icon-name="custom:custom63">
         <div>
             <div>
                 <span>send parent data to son lwc</span>
                 <!-- 引用子组件,名字首字母前加上了 c加上破折号(-),api公开的变量同样。c是默认的命名空间 -->
                 <c-son-lwc item-name={sonItemName}></c-son-lwc>
                 <lightning-button label="alert item info" onclick={handleAlertItemNameEvent}></lightning-button>
             </div>
         </div>
     </lightning-card>
 </template>

parentLwc.js

scala 复制代码
import { LightningElement, api, track, wire } from 'lwc';

export default class ParentLwc extends LightningElement {
    sonItemName = 'test parent for son item';

	handleAlertItemNameEvent() {
		this.template.querySelector('c-son-lwc').alertItemNameInfo();
	}
}

这里使用了button去触发子组件方法,方法中弹出了当前子组件itemName的值,点击后可以观察到,子组件值已被父组件覆盖。说明父组件已经将值传递给子组件,并且也能够触发子组件方法。

1.2 子组件向父组件传递值

第一,子组件需要通过CustomEvent的方式去发出一个事件,由父组件监听。可以使用一个button来做触发动作。

sonLwc.html

xml 复制代码
<template>
    <lightning-button label="send data to parent lwc" onclick={handleSendData}></lightning-button>
</template>

sonLwc.js

scala 复制代码
import { LightningElement, api } from 'lwc';
import LightningAlert from 'lightning/alert';

export default class SonLwc extends LightningElement {
    itemValue = "Hello from Son Component";

    handleSendData() {
        const customEvent = new CustomEvent("senddata", {
            detail: {
                message: this.itemValue,
            }
        });
        this.dispatchEvent(customEvent); // 主要功能是将一个事件对象分发到指定的 DOM 元素上,从而触发该元素上绑定的事件监听器
    }
}

CustomEvent构造时,name建议全小写,detail中可以设这么用于传递的数据。还有诸如bubblescomposed等参数可以设定。请参考Events Best Practices

第二,父组件通过on-eventname监听事件,并从中取到子组件传递的数据。

parentLwc.html

xml 复制代码
 <template>
     <lightning-card title="Parent LWC" icon-name="custom:custom63">
         <div>
             <div>
                 <span>send parent data to son lwc</span>
                 <!-- 引用子组件,名字首字母前加上了 c加上破折号(-),api公开的变量同样。c是默认的命名空间 -->
                 <c-son-lwc onsenddata={handleDataReceived}></c-son-lwc>
                 <p>Data received from Son Component: {receivedMessage}</p>
             </div>
         </div>
     </lightning-card>
 </template>

parentLwc.js

scala 复制代码
 import { LightningElement, api, track, wire } from 'lwc';
 ​
 export default class ParentLwc extends LightningElement {
     receivedMessage;
 ​
     handleDataReceived(event) {
         this.receivedMessage = event.detail.message;
     }
 }

通过点击button,就可以看到子组件的值会传递给父组件。

二、非父子组件传值

对于非父子组件传值,Salesforce提供了Lightning Message Service的标准方法去实现。LMS可以实现LWC,Aura,Visualforce Page之间的跨组件通信。

第一步,需要先创建messageChannels,messageChannels只能通过metadata的方式创建。

xml 复制代码
 <?xml version="1.0" encoding="UTF-8"?>
 <LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
     <description>Message Channel to pass a field value</description>
     <isExposed>true</isExposed>
     <masterLabel>FieldValueTransfer</masterLabel>
 </LightningMessageChannel>

第二步,创建publisher组件

publisherLwc.html

xml 复制代码
 <template>
     <lightning-card title="Publisher Component" icon-name="custom:custom63">
         <div class="slds-m-around_medium">
             <lightning-input label="Enter Message" value={messageText} onchange={handleInputChange}></lightning-input>
             <lightning-button label="Send Message" onclick={handleSend}></lightning-button>
         </div>
     </lightning-card>
 </template>

publishLwc.js

typescript 复制代码
 import { LightningElement, api, track, wire } from 'lwc';
 import { publish, MessageContext } from 'lightning/messageService';
 import MY_MESSAGE_CHANNEL from '@salesforce/messageChannel/FieldValueTransfer__c';
 ​
 export default class PublisherComponent extends LightningElement {
     messageText = '';
 ​
     @wire(MessageContext)
     messageContext;
 ​
     handleInputChange(event) {
         this.messageText = event.target.value;
     }
 ​
     handleSend() {
         const message = { data: this.messageText};
         publish(this.messageContext, MY_MESSAGE_CHANNEL, message);
     }
 }

第三步,创建subscriber组件

subscriberLwc.html

xml 复制代码
 <template>
     <lightning-card title="Subscriber Component" icon-name="custom:custom63">
         <div class="slds-m-around_medium">
             <p>Received Message: {receivedMessage}</p>
         </div>
     </lightning-card>
 </template>

subscriberLwc.js

typescript 复制代码
 import { LightningElement, wire } from 'lwc';
 import { subscribe, MessageContext } from 'lightning/messageService';
 import MY_MESSAGE_CHANNEL from '@salesforce/messageChannel/FieldValueTransfer__c';
 ​
 export default class SubscriberComponent extends LightningElement {
     subscription = null;
     receivedMessage = '';
 ​
     @wire(MessageContext)
     messageContext;
 ​
     connectedCallback() {
         this.subscribeToMessageChannel();
     }
 ​
     subscribeToMessageChannel() {
         if (this.subscription) {
             return;
         }
         this.subscription = subscribe(this.messageContext, MY_MESSAGE_CHANNEL, (message) => {
             this.handleMessage(message);
         });
     }
 ​
     handleMessage(message) {
         this.receivedMessage = message.data;
     }
 }

将publisher和subscriber放到同一个lightning page,就可以观察到效果。由publisher发送一条数据,subscriber就可以接收到这条数据。

关于LMS的更多内容,请见lightning-message-service

相关推荐
二闹8 分钟前
三个注解,到底该用哪一个?别再傻傻分不清了!
后端
用户490558160812520 分钟前
当控制面更新一条 ACL 规则时,如何更新给数据面
后端
林太白22 分钟前
Nuxt.js搭建一个官网如何简单
前端·javascript·后端
码事漫谈23 分钟前
VS Code 终端完全指南
后端
该用户已不存在1 小时前
OpenJDK、Temurin、GraalVM...到底该装哪个?
java·后端
怀刃1 小时前
内存监控对应解决方案
后端
码事漫谈1 小时前
VS Code Copilot 内联聊天与提示词技巧指南
后端
Moonbit2 小时前
MoonBit Perals Vol.06: MoonBit 与 LLVM 共舞 (上):编译前端实现
后端·算法·编程语言
Moonbit2 小时前
MoonBit Perals Vol.06: MoonBit 与 LLVM 共舞(下):llvm IR 代码生成
后端·程序员·代码规范
Moonbit2 小时前
MoonBit Pearls Vol.05: 函数式里的依赖注入:Reader Monad
后端·rust·编程语言