防抖的实战例子 - 常用语echarts图中点击事件的例子

防抖实战

防抖的概念

  • 防抖是一种控制函数执行频率的技术,它确保一个函数在短时间内被多次触发时,只执行一次。

  • 比喻理解

    • 想象电梯关门的过程:
    • 有人进电梯(触发事件)
    • 电梯等待5秒(防抖时间)
    • 如果5秒内又有人进来(再次触发),重新等待5秒
    • 直到5秒内没人进来,电梯才真正关门(执行函数)

描述:在某些图像点击的情况下,比如说 柱状图 或者 饼图,点击事件会造成一下子多次执行操作,此时就可以使用防抖来操作

<template>
  <simple-chart
    ref="chartRef"
    :title="{
      show: false,
    }"
    :resize-delay="0"
    :colors="lineColor"
    :legend="{
      show: false
    }"
    :height="chartHeight"
    :dataset-source="chartData || []"
    :textStyle="{
      color: 'red'
    }"
    :seriesConfig="seriesConfig()"
    :x-axis="{ ...xAxisConfig }"
    :y-axis="[{ ...yAxisConfig }]"
    :grid="{
      top: '5%',
      bottom: '15%',
      left: '4%',
      right: '5%'
    }"
    :bgColor="backgroundColor"
    :data-zoom="[{ type: 'slider', show: false }]"
    :loading-config="{ maskColor: '#FFFFFF11', textColor: '#CCC' }"
    :custom-tooltip="{
      trigger: 'axis',
      axisPointer: { type: 'none' },
      formatter: tooltipFormatter,
      borderColor: '#2861C2'
    }"
    :safeUpdate="isUpdate"
    :markLineShow="true"
    @click-data="debouncedHandleBarClick" 
  >
  </simple-chart>
</template>

<script setup>
import SimpleChart from '@/components/echart/SimpleChart.vue';
import { useRouter } from 'vue-router';
import { debounce } from 'lodash-es';

const router = useRouter(); 
const props = defineProps({            
  chartHeight: {
    type: [String, Number],
    default: '26vh'
  },
  xData: {
    type: Array,
    default: () => ['FOL', 'FVN', 'FJZ', 'FSJ', 'FTX', 'FCZ']
  },
  chartData: {
    type: Array,
    default: () => [
      { name: 'FOL', value: 1509 },
      { name: 'FVN', value: 1467 },
      { name: 'FJZ', value: 993 },
      { name: 'FSJ', value: 478 },
      { name: 'FTX', value: 984 },
      { name: 'FCZ', value: 1005 }
    ]
  },
  chartTitle: {
    type: String,
    default: 'resource'
  },
  isUpdate: {
    type: Boolean,
    default: false
  }, 
  accessBackend: {
    type: Boolean,
    default: false
  }
});

const yAxisMax = computed(() => {
  if (!props.chartData || props.chartData.length === 0) return 2500; 
  const maxValue = Math.max(...props.chartData.map((item) => item.value));
  return maxValue + 100;
});

let xAxisConfig = ref({
  type: 'category',
  axisLine: { lineStyle: { color: 'rgb(185, 232, 255)' }},
  axisLabel: {
    fontSize: 10,
    color: '#B9E8FF',
    interval: 0,
    formatter: (value) => {
      return `{label|${value}}`;
    },
    rich: {
      label: {
        padding: [0, 0, 0, 10],
        color: '#B9E8FF',
        fontSize: 10
      }
    }
  },
  axisTick: {
    show: false
  },
  data: props.xData
});
const yAxisConfig = ref({
  show: true,
  type: 'value',
  name: '',
  min: 0,
  max: yAxisMax.value,
  axisLabel: {
    color: '#B9E8FF',
    fontSize: 10,
    formatter: '{value}'
  },
  axisTick: {
    show: false
  },
  axisLine: {
    show: true,
    symbolOffset: [0, 0],
    symbol: ['none', 'none'],
    lineStyle: {
      color: 'rgb(209, 212, 215)'
    }
  },
  splitLine: {
    show: true,
    lineStyle: {
      width: 1,
      type: 'dashed', 
      color: 'rgb(235, 237, 238, 0.4)'
    }
  }
});

const seriesConfig = () => {
  const backgroundData = props.chartData.map(() => 2500);
  const barData = props.chartData.map((item) => item.value);
  return [
    {
      // 背景矩阵
      data: backgroundData, 
      type: 'bar',
      barWidth: '70%',
      itemStyle: {
        color: 'rgba(108, 130, 151, 0.1)',
        barBorderRadius: [5, 5, 0, 0]
      },
      silent: true,
      tooltip: { show: false }, 
      z: 1
    },
    {
      // 主柱状矩阵
      data: barData, 
      type: 'bar',
      barWidth: '30%',
      barGap: '-73%',
      itemStyle: {
        color: 'rgb(7, 106, 235)',
        barBorderRadius: [3, 3, 0, 0]
      },
      label: {
        show: true,
        position: 'top',
        color: 'rgba(255, 255, 255, 1)',
        fontSize: 12,
        fontWeight: 700,
        formatter: (params) => {
          return params.value;
        }
      },
      z: 2
    }
  ];
};

watch(() => props.chartData, () => {
  yAxisConfig.value.max = yAxisMax.value;
}, { deep: true });

const handleBarClick = (params) => {
  if(!props.accessBackend) {
    // ElMessage.closeAll();
    return ElMessage({
      type: 'error',
      message: "Sorry, you don't have permission, please contact genius team",
      showClose: true,
      duration: 0
    });
  }
  if (params.seriesIndex === 1) {
    router.push({
      path: '/monitoring',
      query: { site: params.name }
    });
  }
};

// 创建防抖函数实例
const debouncedHandleBarClick = debounce(handleBarClick, 300, {
  leading: false,   // 不立即执行
  trailing: true    // 等待结束后执行
});

const tooltipFormatter = (params) => {
  const item = params[0];
  return `${item.marker} ${item.name}: ${item.value}`;
};

onBeforeUnmount(() => {
  debouncedHandleBarClick.cancel();  // 在摧毁之前需要将防抖取消
});
</script>

防抖代码在debounce中已经封装好了,直接使用即可;

  • 创建好的防抖函数实例
    ···
    const debouncedHandleBarClick = debounce(handleBarClick, 300, {
    leading: false, // 不立即执行;事件触发的时候不立即执行函数
    trailing: true // 等待结束后执行
    });
    ···
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值