vue2 echarts饼状图,柱状图,折线图,简单封装以及使用

vue2 echarts饼状图,柱状图,折线图,简单封装以及使用

1. 直接上代码(复制可直接用,请根据自己的文件修改引用地址,图表只是简单封装,可根据自身功能,进行进一步配置。

2. 安装echarts npm install echarts --save

3. 安装 npm install element-resize-detector --save注:该配置在博客最底部 用于 echarts 宽高计算等)

4. 柱状图简单封装

  1. 先上菜单目录
    2. ](https://img-blog.csdnimg.cn/direct/cb6c1c62e1514158bb2c0e0574f0f5c3.png)

  2. 新建 barChart.vue


 // barChart.vue
 
 <template>
  <div :style="{ height: height, width: width }" />
</template>

<script>
import * as echarts from "echarts";
import resize from "@/echarts/mixins/resize";
export default {
  mixins: [resize],
  props: {
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "280px",
    },
    chartData: {
      type: Object,
      required: true,
    },
  },
  data() {
    return {
      chart: null,
    };
  },
  watch: {
    // 监听表数据变化,重新初始化图表
    chartData: {
      deep: true,
      handler(val) {
        if (this.chart) {
          this.$nextTick(() => {
            this.initChart();
          });
        }
      },
    },
  },
  mounted() {
    // 初始化图表
    this.initChart();
  },
  beforeDestroy() {
    // 页面销毁时 销毁图表
    if (!this.chart) {
      return;
    }
    this.chart.dispose();
    this.chart = null;
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$el);
      this.setOptions(this.chartData);
    },
    // 图表配置项
    setOptions(chartData) {
      const { data = [], color = [], yLabel = "" } = chartData;
      const names = data.map((item) => item.name);
      const values = data.map((item) => {
        if (color.length) {
          return {
            value: item.value,
            itemStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                { offset: 0, color: color[0][1] },
                { offset: 1, color: color[0][2] },
              ]),
            },
          };
        } else {
          return {
            value: item.value,
            itemStyle: {
              // 此处设置柱状图的渐变
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                { offset: 0, color: "rgba(19, 179, 228, 0.2)" },
                { offset: 1, color: "rgba(19, 179, 228, 1)" },
              ]),
            },
          };
        }
      });
      const valuesDefaultItem = data.map((item) => {
        if (color.length) {
          // 此处判断 是否使用传入的颜色
          return {
            value: 0,
            itemStyle: {
              color: color[0][3],
            },
            emphasis: {
              itemStyle: {
                color: color[0][3],
              },
            },
          };
        } else {
          return {
            value: 0,
            itemStyle: {  // 柱状图顶部颜色
              color: 'rgb(19, 179, 228)',
            },
            emphasis: {
              itemStyle: {
                color: '#333',  // 柱状图顶部hover时的颜色
              },
            },
          };
        }
      });
      const valuesMax = data.map((item) => item.value / 5);
      const options = {
        grid: {
          top: 50,
          left: 20,
          right: 20,
          bottom: 0,
          containLabel: true,
        },
        tooltip: {
          trigger: "axis",
          formatter: `{b}<br />{c}${yLabel}`,
          axisPointer: {
            // 坐标轴指示器,坐标轴触发有效
            type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
            shadowStyle: {
              color: "#e7baba61", // 鼠标移入时的背景色
            },
          },
          borderColor: "rgb(19, 179, 228)", // 鼠标移入时 悬浮框border样式
          backgroundColor: "rgba(6,167,205,.9)",  // 鼠标移入时 悬浮框背景样式
          padding: 10, // 鼠标移入时 悬浮框padding
          textStyle: { // 鼠标移入时 悬浮框内容样式
            fontSize: 14,
            fontWeight: 400,
            color: "yellow",
          },
        },
        xAxis: {
          data: names,
          nameLocation: "center",
          axisLabel: {
            rotate: 0,
            interval: 0,
            align: "center",
            // X轴  字体样式
            textStyle: {
              color: "#333333",
              fontSize: 12,
              fontWeight: 500,
            },
           
            // 此处设置 X轴  多出3个字符就进行换行(可自定义设置)
  
            // formatter: function (params) {
            //   let newParamsName = ""; // 拼接后的新字符串
            //   let paramsNameNumber = params.length; // 实际标签数
            //   let provideNumber = 3; // 每行显示的字数
            //   let rowNumber = Math.ceil(paramsNameNumber / provideNumber); // 如需换回,算出要显示的行数

            //   if (paramsNameNumber > provideNumber) {
            //     /** 循环每一行,p表示行 */

            //     for (let i = 0; i < rowNumber; i++) {
            //       let tempStr = ""; // 每次截取的字符串
            //       let start = i * provideNumber; // 截取位置开始
            //       let end = start + provideNumber; // 截取位置结束

            //       // 最后一行的需要单独处理

            //       if (i == rowNumber - 1) {
            //         tempStr = params.substring(start, paramsNameNumber);
            //       } else {
            //         tempStr = params.substring(start, end) + "\n";
            //       }
            //       newParamsName += tempStr;
            //     }
            //   } else {
            //     newParamsName = params;
            //   }
            //   return newParamsName;
            // },
          },
          axisTick: {
            show: false,
          },
          axisLine: {
            show: false,
          },
          z: 10,
        },
       dataZoom: [
          {
            type: "inside",
            start: 20, //数据窗口范围的起始百分比。范围是:0 ~ 100。表示 0% ~ 100%。
            end: 100,
            xAxisIndex: 0, //设置控制xAxis
            // yAxisIndex: 0, //设置控制yAxis
            zoomOnMouseWheel: true, //设置鼠标滚轮不能触发缩放。
          },
        ],
        yAxis: {
          name: yLabel, // Y周单位
          nameTextStyle: { // 单位样式
            color: "#333",
            align: "center",
          },
          // y轴刻度样式
          axisLabel: {
            textStyle: {
              color: "#333333",
              fontSize: 12,
              fontWeight: 400,
            },
          },
          // y轴刻度横线样式
          splitLine: {
            lineStyle: {
              color: "#dddddd",
            },
          },
          // 是否显示y轴
          axisLine: {
            show: true,
          },
        },
        series: [
          {
            type: "bar",
            barMaxWidth: 36,
            label: {
              show: true,
              position: "top",
              distance: 4,
              color: "#fff",
              fontSize: 13,
              fontWeight: 400,
              formatter: `{c}`,
            },
            data: values,
            stack: "one",
          },
          // 设置柱状图顶部的样式
          {
            type: "bar",
            barMaxWidth: 60,
            stack: "one",
            barMinHeight: 3,
            barMaxHeight: 3,
            cursor: "default",
            data: valuesDefaultItem,
          },
          {
            type: "bar", //占位
            barMaxWidth: 36, // 设置柱状图宽度
            stack: "one",
            barMinHeight: 3,
            barMaxHeight: 3,
            cursor: "default",
            emphasis: {
              itemStyle: {
                color: "transparent",
              },
            },
            itemStyle: {
              color: "transparent",
            },
            data: valuesMax,
          },
        ],
      };
      console.log(options);
      this.chart.setOption(options);
    },
  },
};
</script>

在这里插入图片描述

5. 柱状图组件使用

<template>
  <div class="about">
    <div class="box-card">
      <div style="width:100%;height:100%">
        <barChart :chartData="chartData" height="100%"></barChart>
      </div>
    </div>
  </div>
</template>
<script>
import barChart from "./components/barChart.vue"; // 柱状图
export default {
  components: {
    barChart,
  },
  data() {
    return {
      chartData: {
        yLabel: "次",
        color: [],
        data: [],
      },
    };
  },
  mounted(){
    // 调用接口
    this.getFaceData()
  },
  methods: {
    getFaceData() {
      // 此处应该调用接口
      // 暂时使用假数据
      this.chartData.data = [
        {
          name: "admin11",
          value: 505,
        },
        {
          name: "lss11",
          value: 600,
        },
        {
          name: "zbw",
          value: 800,
        },
        {
          name: "陌生人",
          value: 902,
        },
      ];
    },
  },
};
</script>
<style lang="scss">
.box-card {
  width: 800px;
  height: 400px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  padding: 20px;
  margin: 20px;
}
</style>

6. 饼状图简单封装

  1. 新建 pieChart.vue

//pieChart.vue

<template>
  <div :style="{ height: height, width: width }" />
</template>
<script>
import * as echarts from "echarts";
import resize from "@/echarts/mixins/resize";
export default {
  mixins: [resize],
  props: {
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "280px",
    },
    chartData: {
      type: Object,
      required: true,
    },
  },
  data() {
    return {
      chart: null,
    };
  },
  watch: {
    // 监听表数据变化,重新初始化图表
    chartData: {
      deep: true,
      handler(val) {
        if (this.chart) {
          this.$nextTick(() => {
            this.initChart();
          });
        }
      },
    },
  },
  mounted() {
    // 初始化图表
    this.initChart();
  },
  beforeDestroy() {
    // 页面销毁时 销毁图表
    if (!this.chart) {
      return;
    }
    this.chart.dispose();
    this.chart = null;
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$el);
      this.setOptions(this.chartData);
    },
    // 图表配置项
    setOptions(chartData) {
      // 图表数据
      const data = chartData.data;
      // 计算图标中心的数据总值
      let sum = data.reduce((pre, cur, index, arr) => {
        return pre + cur.value;
      }, 0);
      // 图表中心显示的名称
      let name = chartData.name;
      const options = {
        // 自定义设置图表颜色
        color: [
          "rgb(53, 136, 229)",
          "rgb(13, 235, 251)",
          "rgb(227, 59, 90)",
          "rgb(255, 147, 38)",
          "rgb(176, 210, 231)",
          "rgb(62, 255, 194)",
          "rgb(138, 92, 247)",
          "rgb(25, 120, 162)",
          "rgb(67, 207, 124)",
          "rgb(255, 195, 0)",
        ],
        // 鼠标hover时显示的浮窗
        tooltip: {
          trigger: "item",
          formatter: "{b}: {c} ({d}%)",
          borderColor: "transparent",
          backgroundColor: "rgba(6,167,205,.9)",
          padding: 10,
          textStyle: {
            fontSize: 14,
            fontWeight: 400,
            color: "#fffafa",
          },
        },
        legend: {
          type: "scroll", //这里添加scroll就可以分页了
          orient: "vertical",  //图例列表的布局朝向 horizontal (默认顶部)vertical(默认右边)
          right: "0%",
          // 'circle'(圆形),'rect(矩形)','roundRect(矩形边角为圆弧)'
          // 'triangle(三角形)','diamond(矩形)','pin(形状类似于锤子的尾部)','arrow(飞机形状)','none'
          icon: "circle",
          top: "10%",
          bottom: "30%",
          // 设置图例文字的样式
          formatter: function (name) {
            console.log(name, 99999999);
            let arr = ["{b|" + name + "}"];
            return arr.join(",");
          },
          textStyle: {
            //样式
            rich: {
              a: {
                fontSize: 10,
                color: "yellow",
              },
              // 设置图例的颜色和文字大小
              b: {
                // 图例文字大小
                fontSize: 10,
                // 图例文字颜色
                color: "red",
              },
            },
          },
        },
        series: [
          {
            minShowLabelAngle: 30,
            type: "pie",
            startAngle: 30,
            radius: ["50%", "70%"],
            center: ["40%", "50%"], // 设置图表的位置
            avoidLabelOverlap: false,
            itemStyle: {
              // 图表块周围的红色边
              // borderColor: "red",
              // 图表块周围的红色边宽度
              // borderWidth: 1,
            },
            // 引导线名称样式
            label: {
              formatter: "{b}  {c}",
              color: "#333",
            },
            // 引导线样式
            labelLine: {
              lineStyle: {
                color: "#dddddd",
              },
            },
            data: data,
          },
          {
            minShowLabelAngle: 5,
            type: "pie",
            center: ["40%", "50%"], // 设置图表的位置
            radius: ["40%", "40%"],
            hoverAnimation: false,
            label: {
              normal: {
                show: true,
                position: "center",
                color: "#333",
                formatter: "{total|" + sum + "}" + "\n\r" + `{active|${name}}`,
                // 总数字样式
                rich: {
                  total: {
                    fontSize: 26,
                    fontWeight: 600,
                    color: "yellow",
                  },
                  // 名称样式
                  active: {
                    fontSize: 14,
                    fontWeight: 400,
                    color: "#f73f62",
                    lineHeight: 30,
                  },
                },
              },
              emphasis: {
                //中间文字显示
                show: true,
              },
            },
            lableLine: {
              normal: {
                show: false,
              },
              emphasis: {
                show: true,
              },
              tooltip: {
                show: false,
              },
            },
            // 内部圈样式
            itemStyle: {
              color: "green",
              borderColor: "green",
              borderWidth: 1,
            },
            tooltip: {
              show: false,
            },
            cursor: "default",
            data: [{ value: 1, name: "1" }],
          },
        ],
      };
      this.chart.setOption(options);
    },
  },
};
</script>

在这里插入图片描述

7. 饼状图组件使用

<template>
  <div class="about">
    <div class="box-card">
      <div style="width:100%;height:100%">
        <pieChart :chartData="chartData" height="100%"></pieChart>
      </div>
    </div>
  </div>
</template>
<script>
// 引入饼图组件
import pieChart from "./components/pieChart.vue";  // 饼状图
export default {
  components: {
    pieChart, // 饼图组件
  },
  data() {
    return {
      chartData: {
        name: "识别总数", // 表名
        data: [], // 表数据
      },
    };
  },
  mounted(){
    // 调用接口
    this.getFaceData()
  },
  methods: {
    getFaceData() {
      // 此处应该调用接口
      // 暂时使用假数据
      this.chartData.data = [
        {
          name: "admin",
          value: 80,
        },
        {
          name: "lss",
          value: 106,
        },
        {
          name: "zbw",
          value: 50,
        },
        {
          name: "陌生人",
          value: 200,
        },{
          name: "admin1",
          value: 80,
        },
        {
          name: "lss1",
          value: 106,
        },
        {
          name: "zbw1",
          value: 50,
        },
        {
          name: "陌生人1",
          value: 200,
        },{
          name: "admin2",
          value: 80,
        },
        {
          name: "lss2",
          value: 106,
        },
        {
          name: "zbw2",
          value: 50,
        },
        {
          name: "陌生人2",
          value: 200,
        },{
          name: "admin3",
          value: 80,
        },
        {
          name: "lss3",
          value: 106,
        },
        {
          name: "zbw3",
          value: 50,
        },
        {
          name: "陌生人3",
          value: 200,
        },
      ];
    },
  },
};
</script>
<style lang="scss">
.box-card {
  width: 800px;
  height: 400px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  padding: 20px;
  margin: 20px;
}
</style>

8. 折线图简单封装

  1. 新建 lineChart.vue

// lineChart.vue

<template>
  <div :style="{ height: height, width: width }" />
</template>

<script>
import * as echarts from "echarts";
import resize from "@/echarts/mixins/resize";
export default {
  mixins: [resize],
  props: {
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "280px",
    },
    chartData: {
      type: Object,
      required: true,
    },
    echartsName: {
      type: String,
      default: "",
    },
    echartsUnit: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      chart: null,
      color: [
        "rgb(62, 255, 194)",
        "rgb(255, 195, 0)",
        "rgb(53, 136, 229)",
        "rgb(13, 235, 251)",
        "rgb(227, 59, 90)",
        "rgb(255, 147, 38)",
        "rgb(176, 210, 231)",
        "rgb(138, 92, 247)",
        "rgb(25, 120, 162)",
        "rgb(67, 207, 124)",
      ],
    };
  },
  watch: {
    // 监听表数据变化,重新初始化图表
    chartData: {
      deep: true,
      handler(val) {
        if (this.chart) {
          this.$nextTick(() => {
            this.initChart();
          });
        }
      },
    },
  },
  mounted() {
    // 初始化图表
    this.initChart();
  },
  beforeDestroy() {
    // 页面销毁时 销毁图表
    if (!this.chart) {
      return;
    }
    this.chart.dispose();
    this.chart = null;
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$el);
      this.setOptions(this.chartData);
    },
    // 图表配置项
    setOptions(chartData) {
      let that = this;
      const name = chartData.name;
      const label = chartData.label;
      let series = [];
      let arr = Object.keys(chartData.data);
      arr.forEach((v, index) => {
        series.push({
          name: name[index],
          type: "line",
          symbol: "circle",
          symbolSize: 6,
          showSymbol: false,
          // 此处是折线图的颜色
          itemStyle: {
            color: that.color[index],
          },
          lineStyle: {
            color: that.color[index],
          },
          // 折线图内部区域的颜色
          areaStyle: {
            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
              { offset: 1, color: "rgba(0, 206, 218, 0.08)" },
              { offset: 0, color: that.color[index] },
            ]),
          },
          data: chartData.data[v],
        });
      });
      const options = {
        // 图例位置
        grid: {
          top: 50,
          left: 50,
          right: 60,
          bottom: 20,
          containLabel: true,
        },
        legend: {
          top: 8,
          data: name,
          textStyle: {
            color: "#333",
            fontSize: 12,
            lineHeight: 20,
          },
        },
        //  此处判断是否使用自定义 浮框
        tooltip: that.echartsName
          ? {
              trigger: "axis",
              axisPointer: {
                type: "line",
                lineStyle: {
                  color: "rgba(0, 206, 218, 1)",
                },
              },
              borderColor: "transparent",
              backgroundColor: "rgba(6,167,205,.9)",
              padding: 10,
              textStyle: {
                fontSize: 14,
                fontWeight: 400,
                color: "#fffafa",
              },
              // 自定义tip
              formatter: function (params) {
                var htmlStr = "<div>动环信息" + "<br/>";
                htmlStr += "名称:" + that.echartsName + "<br/>";
                htmlStr += "数值:" + params[0].value + "<br/>";
                htmlStr += "时间:" + params[0].name + "<br/>";
                htmlStr += "</div>";
                return htmlStr;
              },
            }
          : {
            // 默认tip
              trigger: "axis",
              axisPointer: {
                type: "line",
                lineStyle: {
                  color: "rgba(0, 206, 218, 1)",
                },
              },
              borderColor: "transparent",
              backgroundColor: "rgba(6,167,205,.9)",
              padding: 10,
              textStyle: {
                fontSize: 14,
                fontWeight: 400,
                color: "#fffafa",
              },
            },
       dataZoom: [
          {
            type: "inside",
            start: 20, //数据窗口范围的起始百分比。范围是:0 ~ 100。表示 0% ~ 100%。
            end: 100,
            xAxisIndex: 0, //设置控制xAxis
            // yAxisIndex: 0, //设置控制yAxis
            zoomOnMouseWheel: true, //设置鼠标滚轮不能触发缩放。
          },
        ],
        xAxis: [
          {
            type: "category",
            boundaryGap: false,
            showMinLabel: true,
            showMaxLabel: true,
            data: label,
            axisLabel: {
              // X 轴刻度样式
              textStyle: {
                color: "#333",
                fontSize: 12,
                fontWeight: 500,
              },
            },
            axisTick: {
              show: false,
            },
            axisLine: {
              show: false,
            },
          },
        ],
        yAxis: [
          {
            type: "value",
            minInterval: 1,
            //  Y轴刻度颜色
            axisLabel: {
              textStyle: {
                color: "#333",
                fontSize: 12,
                fontWeight: 400,
              },
            },
            // Y 轴刻度线
            splitLine: {
              lineStyle: {
                color: "#dddddd",
              },
            },
            axisLine: {
              show: false,
            },
            axisTick: {
              show: false,
            },
            name: this.echartsUnit, // Y轴显示 单位
            nameTextStyle: {
              color: "#dddddd",
              padding: [0, 0, 12, 0],
            },
          },
        ],
        series: series,
      };
      this.chart.setOption(options);
    },
  },
};
</script>

9. 折线图组件使用
在这里插入图片描述

<template>
  <div class="about">
    <div class="box-card">
      <lineChart
        :chartData="chartData"
        :echartsName="echartsName"
        :echartsUnit="echartsUnit"
        :height="'calc(100% - 30px)'"
      ></lineChart>
    </div>
  </div>
</template>

<script>
import lineChart from "./components/lineChart.vue"; // 折线图
export default {
  components: { lineChart },
  data() {
    return {
      chartData: {
        name: [],
        label:[],
        data:{
          value:[],
          value1:[],
          // ..........
        }
      },
      echartsName: "", // 自定义名称
      echartsUnit: "", // 单位
    };
  },
  mounted() {
    // 调用接口
    this.getFaceData();
  },
  methods: {
    getFaceData() {
      // 一条线
      // 此处应该调用接口
      // 暂时使用假数据
      this.chartData.name = ['温度']
      this.echartsUnit = 'kg'  // 单位
      this.chartData.label = ["2023-11-29 16:00:37","2023-11-29 18:11:36","2023-11-29 19:04:15","2023-11-29 19:21:09","2023-11-29 19:35:39","2023-11-29 19:49:32","2023-11-30 15:38:58"]
      this.chartData.data.value = [24,13,36,11,18,28,8]
      // 多条线
      // this.chartData.name = ['温度','湿度']
      // this.chartData.data.value1 = [11,18,13,25,9,22,10]

    },
  },
};
</script>
<style lang="scss">
.box-card {
  width: 800px;
  height: 400px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  padding: 20px;
  margin: 20px;
}
</style>

10. 配置 element-resize-detector 公共方法

  1. List item
  2. 在echarts 文件夹下面新建 mixins 文件夹 然后 新建 resize.js
  3. resize.js 代码(可复制直接用)
// resize.js
import elementResizeDetectorMaker from "element-resize-detector";
import { debounce } from '@/utils/index'
export default {
  data() {
    return {
      $_sidebarElm: null,
      $_resizeHandler: null
    };
  },
  mounted() {
    var erd = elementResizeDetectorMaker();
    setTimeout(() => {
      if (this.chart) {
        erd.listenTo(this.chart._dom, ele => {
          debounce(() => {
            if(typeof this.getDomSizeFn === "function"){
              this.getDomSizeFn(ele);
            }
            if (this.chart && this.chart.resize) {
              this.chart.resize();
            }
          }, 100)();
        });
      }
    });
    this.$_resizeHandler = debounce(() => {
      if (this.chart && this.chart.resize) {
        this.chart.resize();
      }
    }, 100);
    this.$_initResizeEvent();
    this.$_initSidebarResizeEvent();
  },
  beforeDestroy() {
    this.$_destroyResizeEvent();
    this.$_destroySidebarResizeEvent();
  },
  // to fixed bug when cached by keep-alive
  // https://github.com/PanJiaChen/vue-element-admin/issues/2116
  activated() {
    this.$_initResizeEvent();
    this.$_initSidebarResizeEvent();
  },
  deactivated() {
    this.$_destroyResizeEvent();
    this.$_destroySidebarResizeEvent();
  },
  methods: {
    // use $_ for mixins properties
    // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
    $_initResizeEvent() {
      window.addEventListener("resize", this.$_resizeHandler);
    },
    $_destroyResizeEvent() {
      window.removeEventListener("resize", this.$_resizeHandler);
    },
    $_sidebarResizeHandler(e) {
      if (e.propertyName === "width") {
        this.$_resizeHandler();
      }
    },
    $_initSidebarResizeEvent() {
      this.$_sidebarElm = document.getElementsByClassName(
        "sidebar-container"
      )[0];
      this.$_sidebarElm &&
        this.$_sidebarElm.addEventListener(
          "transitionend",
          this.$_sidebarResizeHandler
        );
    },
    $_destroySidebarResizeEvent() {
      this.$_sidebarElm &&
        this.$_sidebarElm.removeEventListener(
          "transitionend",
          this.$_sidebarResizeHandler
        );
    }
  }
};

  1. 在 utils 新建 index.js (可复制直接用)

// index.js

/**
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export function debounce (func, wait, immediate) {
    let timeout, args, context, timestamp, result
  
    const later = function () {
      // 据上一次触发时间间隔
      const last = +new Date() - timestamp
  
      // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
      if (last < wait && last > 0) {
        timeout = setTimeout(later, wait - last)
      } else {
        timeout = null
        // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
        if (!immediate) {
          result = func.apply(context, args)
          if (!timeout) context = args = null
        }
      }
    }
  
    return function (...args) {
      context = this
      timestamp = +new Date()
      const callNow = immediate && !timeout
      // 如果延时不存在,重新设定延时
      if (!timeout) timeout = setTimeout(later, wait)
      if (callNow) {
        result = func.apply(context, args)
        context = args = null
      }
      return result
    }
  }
  1. 以上为全部代码,请根据自身需求进行修改配置,完!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/224438.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux文件管理(1)》(25)

《Linux操作系统原理分析之Linux文件管理&#xff08;1&#xff09;》&#xff08;25&#xff09; 8 Linux文件管理8.1 Linux 文件系统概述8.2 EXT2 文件系统8.2.1 EXT2 文件系统的构造8.2.2 EXT2 超级块&#xff08;super block&#xff09;8.2.3 组描述符8.2.4 块位图 8.3 EX…

Linux 进程地址空间

文章目录 进程地址空间进程地址空间结构页表虚拟内存写时拷贝 进程地址空间 进程地址空间难以定义&#xff0c;因为它更像是一个中间件。 程序从磁盘中加载到内存&#xff0c;程序的执行需要硬件资源&#xff0c;所以每个程序启动时会创建至少一条进程&#xff0c;进程作为组…

layui日历插件

layui日历插件: 在已开源的layui日历插件的基础上的改版&#xff08;原版插件地址&#xff1a;https://gitee.com/smalldragen/lay-calender-mark&#xff09;https://gitee.com/tangmaozizi/layui-calendar-plugin.gitjava后台代码并没有把项目完整结构上传上去&#xff0c;因…

敏捷:应对软件定义汽车时代的开发模式变革

随着软件定义汽车典型应用场景的落地&#xff0c;汽车从交通工具转向智能移动终端的趋势愈发明显。几十年前&#xff0c;一台好车的定义主要取决于高性能的底盘操稳与动力系统&#xff1b;几年前&#xff0c;一台好车的定义主要取决于智能化系统与智能交互能否满足终端用户的用…

分类预测 | Matlab实现OOA-SVM鱼鹰算法优化支持向量机的多变量输入数据分类预测

分类预测 | Matlab实现OOA-SVM鱼鹰算法优化支持向量机的多变量输入数据分类预测 目录 分类预测 | Matlab实现OOA-SVM鱼鹰算法优化支持向量机的多变量输入数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现OOA-SVM鱼鹰算法优化支持向量机的多变量输…

Python中组合数据类型

1.常见的组合类型有3大类&#xff1a; 集合类型&#xff1a;是一个元素集合&#xff0c;元素之间无序&#xff0c;相同元素在集合中唯一存在。集合&#xff08;set&#xff09;序列类型&#xff1a;是一个元素向量&#xff0c;元素之间存在先后关系&#xff0c;通过序号访问&a…

sklearn随机森林 测试 路面点云分类

一、特征5个坐标 坐标-特征-类别 训练数据 二、模型训练 记录分享给有需要的人&#xff0c;代码质量勿喷 import numpy as np import pandas as pd import joblib#region 1 读取数据 dir D:\\py\\RandomForest\\ filename1 trainRS filename2 .csv path dirfilename1file…

QT 中基于 TCP 的网络通信 (备查)

基础 基于 TCP 的套接字通信需要用到两个类&#xff1a; 1&#xff09;QTcpServer&#xff1a;服务器类&#xff0c;用于监听客户端连接以及和客户端建立连接。 2&#xff09;QTcpSocket&#xff1a;通信的套接字类&#xff0c;客户端、服务器端都需要使用。 这两个套接字通信类…

基于PicGo实现Typora图片自动上传GitHub

文章目录 一. 引言二. 原理三. 配置3.1 GitHub 设置3.2 下载配置 PicGo3.3 配置 Typora3.4 使用 一. 引言 Typora是一款非常好的笔记软件&#xff0c;但是有一个比较不好的地方&#xff1a;默认图片是存放在本地缓存中。这就会导致文件夹一旦被误删或电脑系统重装而忘记备份文件…

6.1810: Operating System Engineering 2023 <Lab4 traps: Traps>

一、本节任务 二、要点&#xff08;Traps and system calls&#xff09; 有三种事件会使 CPU 暂停当前的指令执行&#xff0c;并强制将控制转移到处理该事件的特殊代码中&#xff1a; 系统调用&#xff08;ecall&#xff09;&#xff1b;异常&#xff08;如非法指令&#xff…

VSCode之C++ CUDA入门:reduce的N+1重境界

背景 Reduce是几乎所有多线程技术的基础和关键&#xff0c;同样也是诸如深度学习等领域的核心&#xff0c;简单如卷积运算&#xff0c;复杂如梯度聚合、分布式训练等&#xff0c;了解CUDA实现reduce&#xff0c;以及优化reduce是理解CUDA软硬件连接点的很好切入点。 硬件环境&…

JVM 分析GC日志

GC日志参数 -verbose:gc 输出gc日志信息&#xff0c;默认输出到标准输出 -XX:PrintGC 输出GC日志。类似&#xff1a;-verbose:gc -XX:PrintGCDetails 在发生垃圾回收时打印内存回收详细的日志&#xff0c;并在进程退出时输出当前内存各区域分配情况 -XX:PrintGCTimeStam…

【TiDB理论知识10】TiDB6.0新特性

新特性 Placement Rules in SQL 小表缓存 内存悲观锁 Top SQL TiDB Enterprise Manager 一 Placement Rules in SQL Placement Rules in SQL 之前会遇到的问题 比如 北京的业务需要访问 T2 和 T3表 &#xff0c;但是T3表的数据在纽约 纽约的业务需要问访T4 T5 T6表…

2023 金砖国家职业技能大赛网络安全省赛理论题样题(金砖国家未来技能挑战赛)

2023 金砖国家职业技能大赛网络安全省赛理论题样题&#xff08;金砖国家未来技能挑战赛&#xff09; 一、参加比赛的形式 团队参与&#xff0c;每队2名选手&#xff08;设队长1名&#xff09;。 二、项目项目阶段简介 项目由四个阶段组成&#xff0c;将按顺序完成。向参与者…

Notes数据直接在Excel中统计

大家好&#xff0c;才是真的好。 我希望你看过前面两篇内容《Domino REST API安装和运行》和《Domino REST API安装和运行》&#xff0c;因为今天我们正是使用REST API方式在Excel中查询和统计Notes数据。 不过首先你得知道一个OData协议&#xff0c;全名Open Data Protocol(…

Leetcode1038. 从二叉搜索树到更大和树

Every day a Leetcode 题目来源&#xff1a;1038. 从二叉搜索树到更大和树 解法1&#xff1a;中序遍历 观察示例 1&#xff0c;我们发现了规律&#xff1a; 二叉搜索树的中序遍历是一个单调递增的有序序列。 本题中要求我们将每个节点的值修改为原来的节点值加上所有大于它…

CSS——选择器、PxCook软件、盒子模型

1、选择器 1.1 结构伪类选择器 作用&#xff1a;根据元素的结构关系查找元素。 1.1.1 :nth-child&#xff08;公式&#xff09; 作用&#xff1a;根据元素的结构关系查找多个元素 <!DOCTYPE html> <html lang"en"> <head><meta charset"…

编程过程中出现bug如何应对?

编程过程中出现bug如何应对&#xff1f; 1.找错误原因 如果完全不知道出错的原因&#xff0c;或者说存在着很多错误的有原因&#xff0c;----》控制变量法 例如&#xff0c;昨天我在使用torchrun 多卡并行一个程序的时候&#xff0c;出现了大量的bug, 于是我将报错信息放在网…

Java动态代理实现与原理详细分析

Java动态代理实现与原理详细分析 关于Java中的动态代理&#xff0c;我们首先需要了解的是一种常用的设计模式–代理模式&#xff0c;而对于代理&#xff0c;根据创建代理类的 时间点&#xff0c;又可以分为静态代理和动态代理。 1、代理模式 代理模式是常用的java设计模式&…
最新文章