Salesforce LWC非父子组件之间的通信

313 阅读1分钟

LWC组件直接的通信第三种类型:非父子关系。LWC使用LMS(闪电消息服务)消息发布与订阅服务,实现跨 DOM 的子树之间的通信

image.png

创建消息通道

  1. 新建文件夹与LWC同级:messageChannels
  2. messageChannels 文件夹下,新建文件:Count_Updated.messageChannel-meta.xml
  3. 替换以下代码:
<?xml version="1.0" encoding="UTF-8" ?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
    <masterLabel>CountUpdated</masterLabel>
    <isExposed>true</isExposed>
    <description>这是一个消息通道,名为CountUpdated,引用的时候为Count_Updated__c</description>
    <lightningMessageFields>
        <fieldName>operator</fieldName>
        <description>This is the operator type of the manipulation</description>
    </lightningMessageFields>
    <lightningMessageFields>
         <fieldName>constant</fieldName>
        <description>This is the number for the manipulation</description>
     </lightningMessageFields>
</LightningMessageChannel>

创建发布者组件

  1. 新建LWC:remoteControl
  2. remoteControl.js
import { publish, MessageContext } from 'lightning/messageService';
import { LightningElement, wire } from 'lwc';
import COUNT_UPDATED_CHANNEL from '@salesforce/messageChannel/Count_Updated__c';

export default class RemoteControl extends LightningElement {
    @wire(MessageContext)
    messageContext;

    handleIncrement() {
        // this.counter++;
        const payload = {
            operator: 'add',
            constant: 1
        };
        publish(this.messageContext, COUNT_UPDATED_CHANNEL, payload);
    }

    handleDecrement() {
        // this.counter--;
        const payload = {
            operator: 'subtract',
            constant: 1
        };
        publish(this.messageContext, COUNT_UPDATED_CHANNEL, payload);
    }

    handleMultiply(event) {
        const factor = event.detail;
        // this.counter *= factor;
        const payload = {
            operator: 'multiply',
            constant: factor
        };
        publish(this.messageContext, COUNT_UPDATED_CHANNEL, payload);
    }
}
  1. remoteControl.htm
<template>
    <lightning-card title="Remote Control" icon-name="action:change_record_type">
        <c-controls class="slds-show slds-is-relative" onadd={handleIncrement} onsubtract={handleDecrement}
            onmultiply={handleMultiply}>
        </c-controls>
    </lightning-card>
</template>

controls 组件在上两篇文章中已创建

  1. remoteControl.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
  <apiVersion>55.0</apiVersion>
  <isExposed>true</isExposed>
  <targets>
    <target>lightning__AppPage</target>
  </targets>
</LightningComponentBundle>

创建订阅者组件

  1. 新建LWC:counts
  2. counts.js
import { subscribe, MessageContext, unsubscribe } from 'lightning/messageService';
import { LightningElement, wire } from 'lwc';
import COUNT_UPDATED_CHANNEL from '@salesforce/messageChannel/Count_Updated__c';

export default class Counts extends LightningElement {
    subscription = null;
    priorCount = 0;
    counter = 0;

    @wire(MessageContext)
    messageContext;

    subscribeToMessageChannel() {
        this.subscription = subscribe(
            this.messageContext,
            COUNT_UPDATED_CHANNEL,
            (message) => this.handleMessage(message)
        );
    }
    
    unsubscribeToMessageChannel() {
        unsubscribe(this.subscription);
        this.subscription = null;
    }

    handleMessage(message) {
        this.priorCount = this.counter;
        if (message.operator == 'add') {
            this.counter += message.constant;
        } else if (message.operator == 'subtract') {
            this.counter -= message.constant;
        } else {
            this.counter *= message.constant;
        }
    }

    connectedCallback() {
        this.subscribeToMessageChannel();
    }
    
    disconnectedCallback() {
        this.unsubscribeToMessageChannel();
    }
}
  1. counts.html
<template>
    <lightning-card title="Counts" icon-name="action:change_record_type">
        <p class="slds-text-align_center slds-var-m-vertical_medium">
          Prior Count: <lightning-formatted-number value={priorCount}></lightning-formatted-number>
        </p>
        <p class="slds-text-align_center slds-var-m-vertical_medium">
          Count: <lightning-formatted-number value={counter}></lightning-formatted-number>
        </p>
      </lightning-card>
</template>
  1. counts.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
  <apiVersion>55.0</apiVersion>
  <isExposed>true</isExposed>
  <targets>
    <target>lightning__AppPage</target>
  </targets>
</LightningComponentBundle>

image.png

当点击 Add 按钮时,remoteControl 组件发布消息 { operator: 'add', constant: 1 },counts 组件订阅该消息:subscribe(this.messageContext, COUNT_UPDATED_CHANNEL, (message) => {});

参考文档:[1]闪电消息服务LMS