Vue3使用mitt进行组件通信 您所在的位置:网站首页 mitt系统 Vue3使用mitt进行组件通信

Vue3使用mitt进行组件通信

2024-06-14 21:21| 来源: 网络整理| 查看: 265

mitt:事件总线,是第三方插件。

Vue2.x 使用 EventBus 事件总线进行兄弟组件通信,而在Vue3中 EventBus 事件总线模式已经被移除,官方建议使用外部的、实现了事件触发器接口的库,例如 mitt 或 tiny-emitter。

比起 Vue 实例上的 EventBus,mitt.js 好在哪里呢?

首先它足够小,仅有200bytes。其次支持全部事件的监听和批量移除。它还不依赖 Vue 实例,可以跨框架使用,React 或者 Vue,甚至 jQuery 项目都能使用同一套库。 1、安装 mitt npm install --save mitt 2、在公共文件 utils 下新建 mitter.ts文件,简单封装下 mitt

utils/mitter.ts

import mitt from 'mitt'; const mitter = mitt(); export default mitter;

在这里插入图片描述 在这里插入图片描述

3、使用

utils/request.ts

如果登录过期,派发 token-expired 事件。 在这里插入图片描述

import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'; import { showMessage } from './errorCode'; import { alertController } from '@ionic/vue'; import { showToast } from '.'; import { StorageService } from './storageService'; import mitter from './mitter'; let token: string = ''; // 是否显示重新登录 let isReloginShow: boolean = false; const storageService = new StorageService(); storageService.create(); axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'; // 创建axios实例 const service = axios.create({ baseURL: importa.env.VITE_APP_ENV == 'development' ? importa.env.VITE_APP_BASE_API : importa.env.VITE_APP_BASE_URL, // 设置API的基础URL timeout: 10000, // 设置请求超时时间 }); const presentAlert = async () => { const alert = await alertController.create({ header: '系统提示', message: '登录状态已过期,您可以继续留在该页面,或者重新登录', buttons: [ { text: '取消', role: 'cancel', handler: () => { console.log('Alert canceled'); isReloginShow = false; }, }, { text: '重新登录', role: 'confirm', handler: () => { console.log('Alert confirmed'); isReloginShow = false; mitter.emit('token-expired'); }, }, ], }); await alert.present(); }; // 请求拦截器 service.interceptors.request.use( async (config: AxiosRequestConfig): Promise => { // showLoading(); // 是否需要设置 token const isToken = (config.headers || {}).isToken === false const headers = config.headers || {}; token = await storageService.getItem("token"); if (token && !isToken) { headers['Authorization'] = 'Bearer ' + token; // 让每个请求携带自定义token 请根据实际情况自行修改 // headers['token'] = token; config.headers = headers; } // return new Promise((resolve, reject) => { // resolve(config) // }) return config; }, (error: AxiosError) => { // 处理请求错误 return Promise.reject(error); } ); // 响应拦截器 service.interceptors.response.use( (response: AxiosResponse) => { // 对响应数据进行处理 // 未设置状态码则默认成功状态 const code = response.data.code || 200; // 获取错误信息 const msg = response.data.msg || showMessage(code) || showMessage('default'); // 二进制数据则直接返回 if (response.request.responseType === 'blob' || response.request.responseType === 'arraybuffer') { return response.data } if (code === 401) { if (!isReloginShow) { isReloginShow = true; presentAlert(); } return Promise.reject('无效的会话,或者会话已过期,请重新登录。') } else if (code === 500) { showToast(msg); return Promise.reject(new Error(msg)) } else if (code !== 200) { showToast(msg); return Promise.reject('error') } else { return response.data } // return response; }, (error: AxiosError) => { // 处理响应错误 return Promise.reject(error); } ); export { service as request }

src/HomePage.vue

在首页监听 token-expired 登录过期事件, 在离开页面时移出监听事件。

在这里插入图片描述

import { IonPage, IonSearchbar, IonList, IonItem, IonLabel, IonSegment, IonSegmentButton, IonIcon, onIonViewWillEnter, onIonViewDidEnter, onIonViewWillLeave, modalController, IonNote, IonContent, IonHeader, } from "@ionic/vue"; import { ref, inject } from "vue"; import * as echarts from "echarts"; import { StorageService } from "@/utils/storageService"; import { getAreaSituation, getCountrySamplePie, getNotify, getSampleInfo, getSampleInfoList } from "@/api/home"; import mitter from "@/utils/mitter"; import { useRouter } from "vue-router"; import HomeSearchDetails from "@/components/HomeSearchDetails.vue"; import { chevronForwardOutline } from "ionicons/icons"; import { QRScanner, registerKeyCodeReceiver, unregisterReceiver, UHFNotifyListeners, UHFRemoveAllListeners, addListenerRate, getEPC } from "@/utils/ratePlugin"; import { showToast } from "@/utils"; const router = useRouter(); const keyWords = ref(""); const areaList = ref([]); const selectedArea = ref(null); const inventoryStatisticsPieChart = ref(null); let pieChart: echarts.ECharts; const seriesData = ref([]); const messageList = ref([]); const searchList = ref([]); const storageService = inject("storageService") as StorageService; onIonViewWillEnter(async () => { const token = await storageService.getItem("token"); const userInfo = await storageService.getItem("userInfo"); // console.log(token, "首页token", JSON.parse(userInfo)); getAreaList(); getNotifyData(); }); onIonViewDidEnter(() => { window.addEventListener("resize", handleResize); mitter.on("token-expired", () => { // console.log("token失效,跳转到登录页面"); router.push("/login"); }); getChartData(); }); onIonViewWillLeave(() => { window.removeEventListener("resize", handleResize); if (pieChart) { pieChart.dispose(); } mitter.off("token-expired"); }); const handleInput = (event: Event) => { // keyWords.value = (event.target as HTMLInputElement).value; // console.log("搜索:", keyWords.value); searchList.value = []; if (keyWords.value) { getSampleInfo(keyWords.value).then((res: any) => { if (res.code === 200) { searchList.value = res.data; } }) } }; const segmentChange = (event: Event) => { let val: string = (event.target as HTMLInputElement).value; selectedArea.value = areaList.value.find((item) => item.areaName == val); }; const initChart = () => { pieChart = echarts.init(inventoryStatisticsPieChart.value); let option = { title: { text: "99865", subtext: "库存总量", left: "14%", top: "center", textStyle: { fontSize: 20, }, subtextStyle: { fontSize: 18, }, }, tooltip: { trigger: "item", }, legend: { top: "center", type: "scroll", right: 0, orient: "vertical", formatter: (name: string) => { let total = 0; let target = 0; seriesData.value.forEach((item) => { total += item.value; if (item.name == name) { target = item.value; } }); let percent = total ? ((target / total) * 100).toFixed(2) : 0; return `${name} ${percent}% ${target}`; }, }, series: [ { // name: "Access From", type: "pie", radius: ["70%", "90%"], right: "50%", avoidLabelOverlap: false, label: { show: false, position: "center", }, labelLine: { show: false, }, data: seriesData.value, }, ], }; option && pieChart.setOption(option); }; const handleResize = () => { setTimeout(() => { if (pieChart) { pieChart.resize(); } }, 500); }; const getAreaList = () => { getAreaSituation().then((res: any) => { if (res.code === 200) { areaList.value = res.data; selectedArea.value = areaList.value[0]; } }); }; const getChartData = () => { getCountrySamplePie().then((res: any) => { if (res.code === 200) { seriesData.value = res.data; initChart(); } }); }; const getNotifyData = () => { getNotify().then((res: any) => { if (res.code === 200) { messageList.value = res.data; } }); };

参考:Vue3 mitt 组件通信 - 附完整示例



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有