Skip to content

消息发布订阅示例

消息发布订阅主要用于解决页面中不同层级的组件之前通讯的问题

代码示例

主页面

  • 主页面中用到了头部区域组件与内容区域组件,两个组件之间需要进行通讯,这个时候就可以用到消息发布订阅
vue
<template>
  <!-- 容器 -->
  <div>
    <!-- 头部区域 -->
    <v-header :unique="unique" />
    <!-- 内容区域 -->
    <v-content :unique="unique" />
  </div>
</template>
<script>
import util from '@/assets/js/util';
import vHeader from '@/modules/pex/components/header';
import vContent from '@/modules/pex/components/content';

export default {
  components: {
    vHeader,
    vContent,
  },
  data() {
    return {
      unique: util.generateShortId(true), //TODO:当前页面唯一的key
    };
  },
};
</script>

常量文件

vue
/**
 * 消息主题
 */
export const TOPIC = {
  PEX_BILL_QUERY_REFRESH: 'PEX_BILL_QUERY_REFRESH', //单据查询刷新操作
};

头部区域

  • TODO:发布消息时,应该保证当前页面的消息主题具有唯一性,如果消息主题不唯一,则同时打开多个页面时,可能存在消息订阅错乱的问题(例如报销系统单据新增页面,由于单据块组件会在不同类型的报销单新增页面使用,所以同时打开多类型单据报销页面时,不同类型的单据新增页面的消息主题应该具有唯一性,以保证同一个组件块在不同页面使用时消息主题不会相互干扰)
  • TODO:可以通过消息主题与当前页面唯一的key结合起来使用,保证唯一性
  • TODO:发布消息时,可以通过全局对象$observablepublish方法来发布消息,publish方法第一个参数为消息主题,第二个参数开始是可选参数,可供发布消息时额外的传递参数,可同时传递多个参数
vue
<template>
  <!-- 头部区域 -->
  <el-button @click="onRefresh">刷新</el-button>
</template>
<script>
import { TOPIC } from '@/modules/pex/common/constant';

export default {
  props: {
    unique: String, //当前页面唯一的key
  },
  methods: {
    /**
     * 处理刷新
     * 1、发布消息通知内容区域进行更新
     */
    onRefresh() {
      // TODO:发布消息时,应该保证当前页面的消息主题具有唯一性,如果消息主题不唯一,则同时打开多个页面时,可能存在消息订阅错乱的问题(例如报销系统单据新增页面,由于单据块组件会在不同类型的报销单新增页面使用,所以同时打开多类型单据报销页面时,不同类型的单据新增页面的消息主题应该具有唯一性,以保证同一个组件块在不同页面使用时消息主题不会相互干扰)
      // TODO:可以通过消息主题与当前页面唯一的key结合起来使用,保证唯一性
      // TODO:发布消息时,可以通过全局对象$observable的publish方法来发布消息,publish方法第一个参数为消息主题,第二个参数开始是可选参数,可供发布消息时额外的传递参数,可同时传递多个参数
      let params = {};
      this.$observable.publish(
        `${TOPIC.PEX_BILL_QUERY_REFRESH}${this.unique}`,
        params
      );
    },
  },
};
</script>

内容区域

  • TODO:组件创建时,需要订阅消息
  • TODO:订阅消息时,可以通过全局对象$observablesubscribe方法来订阅消息,subscribe方法第一个参数为消息主题,第二个参数为处理消息的函数
  • TODO:取消订阅消息时,可以通过全局对象$observableunsubscribe方法来订阅消息,unsubscribe方法第一个参数为消息主题,第二个参数为处理消息的函数
  • TODO:处理接受到的消息
  • TODO:组件销毁时,需要取消订阅消息
vue
<!-- 内容区域 -->
<template>
</template>
<script>
import { TOPIC } from '@/modules/pex/common/constant';

export default {
  props: {
    unique: String, //当前页面唯一的key
  },
  created() {
    // TODO:组件创建时,需要订阅消息
    this.subscribe();
  },
  methods: {
    /**
     * 消息订阅
     * 1、订阅单据查询刷新操作
     */
    subscribe() {
      // TODO:订阅消息时,可以通过全局对象$observable的subscribe方法来订阅消息,subscribe方法第一个参数为消息主题,第二个参数为处理消息的函数
      this.$observable.subscribe(
        `${TOPIC.PEX_BILL_QUERY_REFRESH}${this.unique}`,
        this.onBillQueryRefresh
      );
    },
    /**
     * 取消订阅
     * 1、取消订阅单据查询刷新操作
     */
    unsubscribe() {
      // TODO:取消订阅消息时,可以通过全局对象$observable的unsubscribe方法来订阅消息,unsubscribe方法第一个参数为消息主题,第二个参数为处理消息的函数
      this.$observable.unsubscribe(
        `${TOPIC.PEX_BILL_QUERY_REFRESH}${this.unique}`,
        this.onBillQueryRefresh
      );
    },
    /**
     * 处理单据查询刷新操作
     */
    onBillQueryRefresh(params) {
      // TODO:处理接受到的消息
    },
  },
  beforeDestroy() {
    // TODO:组件销毁时,需要取消订阅消息
    this.unsubscribe();
  },
};
</script>