, ,

封装websocket

使用socket.io-client 使用

npm install socket.io-client

使用socket.io-client

import { io, type Socket } from "socket.io-client";
import { ref } from "vue";

interface WbeSocketOptions { 
  autoConnect?: boolean;
  reconnectionAttempts?: number;
  reconnectionDelay?: number;
}

type WebSocketStatus = "connecting" | "connected" | "disconnected" | "error";
type EventCallback<T=any> = (data: T) => void;


export default function useWebSocket(
  url: string,
  options: WbeSocketOptions = {}
) { 
  const { 
    autoConnect = true,
    reconnectionAttempts = 5,
    reconnectionDelay = 3000
  } = options;

  // 响应式状态
  const socket = ref<Socket | null>(null);
  const connectionStatus = ref<WebSocketStatus>("disconnected");
  const lastError = ref<Error | null>(null);
  const eventCallbacks = new Map<string, EventCallback>();

  // 初始化Socket.IO
  const initSocket = () => {
    socket.value = io(url, { autoConnect, reconnectionAttempts, reconnectionDelay });

    socket.value.on("connect", () => {
      connectionStatus.value = "connected";
      lastError.value = null;
    });

    socket.value.on("disconnect", () => {
      connectionStatus.value = "disconnected";
    });

    socket.value.on("error", (error: Error) => {
      connectionStatus.value = "error";
      lastError.value = error;
    });

    // 通用的消息处理
    socket.value.onAny((eventName: string, data: any) => {
      const callback = eventCallbacks.get(eventName);
      if (callback) {
        callback(data);
      }
    })
  };

  // 订阅事件
  const subscribe = <T>(eventName:string, callback:EventCallback<T>) => { 
    eventCallbacks.set(eventName, callback);
  }

  // 取消订阅
  const unsubscribe = (eventName: string) => { 
    eventCallbacks.delete(eventName);
  }

  // 手动连接
  const connect = () => { 
    if (!socket.value) { 
      initSocket();
    }
    socket.value?.connect();
  }

  const disconnect = () => {
    socket.value?.disconnect();
    eventCallbacks.clear();
  }

  if(autoConnect) { 
    initSocket();
  }

  return {
    socket,
    connectionStatus,
    lastError,
    subscribe,
    unsubscribe,
    connect,
    disconnect
  }
}

使用

<template>
  <div class="screen-block">
    <Title>销售统计</Title>
    <div style="width: 100%; height: 90%">
      <v-chart :option="option" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from "vue";
import Title from "../Title.vue";
import * as echarts from "echarts";
import useWebSocket from "@/composables/useWebSocket";

const { subscribe } = useWebSocket('http://localhost:3000', {
  autoConnect: true,
})

const option = ref({})


const initOption = () => { 
  option.value = {
    tooltip: {
      trigger: "axis",
      axisPointer: {
        type: "line",
        z: 0,
        lineStyle: {
          color: "#2d3443",
        },
      },
    },
    //x轴
    xAxis: {
      splitLine: { show: false }, // 是否显示网格线
      axisLine: { show: true }, // 是否显示轴线
      type: "value", // 作为数据展示
    },
    //y轴
    yAxis: {
      type: "category",
      data: [],
      inverse: true, // y轴反向
      axisLine: { show: true }, // 是否显示轴线
      axisTick: { show: false }, // 是否显示刻度
      axisLabel: {
        color: "#fff",
      },
    },
    grid: {
      top: "3%",
      right: "4%",
      bottom: "3%",
      left: "3%",
      containLabel: true,
    },
    series: [
      {
        type: "bar",
        label: {
          show: true,
          position: "right",
        },
        data: [],
        barWidth: 22,
        roundCap: true,
        showBackground: true,
        backgroundStyle: {
          color: "rgba(220, 220, 220, 0.3)",
        },
        itemStyle: {
          borderWidth: 0,
          borderRadius: [0, 10, 10, 0],
          color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
            {
              offset: 0,
              color: "#00fffb",
            },
            {
              offset: 1,
              color: "#0061ce",
            },
          ]),
        },
      },
    ],
  };
} 

onMounted(() => {
  initOption()
})

const updateOption = (data: Array<{name:string, value:number}>) => { 
  const categories = data.map((item) => item.name)
  const values = data.map((item) => item.value)

  option.value = {
    yAxis: {
      data: categories,
    },
    series: [
      {
        data: values,
      },
    ],
  }
}

subscribe('salesData', updateOption)
</script>

<style lang="scss" scoped>
.screen-block {
  width: 100%;
  height: 100%;
}
</style>

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

About the Author

每个人都有自己得时区,在自己得时区里,一切都是准时的。

BlockSpare — News, Magazine and Blog Addons for (Gutenberg) Block Editor