【vben3源码解读】【useEcharts】【VueUse】详解useEcharts这个hooks的作用与相关库的使用(VueUse)

源代码

import type { EChartsOption } from 'echarts';

import type { Ref } from 'vue';

import type { Nullable } from '@vben/types';

import type EchartsUI from './echarts-ui.vue';

import { computed, nextTick, watch } from 'vue';

import { usePreferences } from '@vben/preferences';

import {
  tryOnUnmounted,
  useDebounceFn,
  useResizeObserver,
  useTimeoutFn,
  useWindowSize,
} from '@vueuse/core';

import echarts from './echarts';

type EchartsUIType = typeof EchartsUI | undefined;

type EchartsThemeType = 'dark' | 'light' | null;

function useEcharts(chartRef: Ref<EchartsUIType>) {
  let chartInstance: echarts.ECharts | null = null;
  let cacheOptions: EChartsOption = {};

  const { isDark } = usePreferences();
  const { height, width } = useWindowSize();
  const resizeHandler: () => void = useDebounceFn(resize, 200);

  const getOptions = computed((): EChartsOption => {
    if (!isDark.value) {
      return {};
    }

    return {
      backgroundColor: 'transparent',
    };
  });

  const initCharts = (t?: EchartsThemeType) => {
    const el = chartRef?.value?.$el;
    if (!el) {
      return;
    }
    chartInstance = echarts.init(el, t || isDark.value ? 'dark' : null);

    return chartInstance;
  };

  const renderEcharts = (
    options: EChartsOption,
    clear = true,
  ): Promise<Nullable<echarts.ECharts>> => {
    cacheOptions = options;
    const currentOptions = {
      ...options,
      ...getOptions.value,
    };
    return new Promise((resolve) => {
      if (chartRef.value?.offsetHeight === 0) {
        useTimeoutFn(async () => {
          resolve(await renderEcharts(currentOptions));
        }, 30);
        return;
      }
      nextTick(() => {
        useTimeoutFn(() => {
          if (!chartInstance) {
            const instance = initCharts();
            if (!instance) return;
          }
          clear && chartInstance?.clear();
          chartInstance?.setOption(currentOptions);
          resolve(chartInstance);
        }, 30);
      });
    });
  };

  function resize() {
    chartInstance?.resize({
      animation: {
        duration: 300,
        easing: 'quadraticIn',
      },
    });
  }

  watch([width, height], () => {
    resizeHandler?.();
  });

  useResizeObserver(chartRef as never, resizeHandler);

  watch(isDark, () => {
    if (chartInstance) {
      chartInstance.dispose();
      initCharts();
      renderEcharts(cacheOptions);
      resize();
    }
  });

  tryOnUnmounted(() => {
    // 销毁实例,释放资源
    chartInstance?.dispose();
  });
  return {
    renderEcharts,
    resize,
    getChartInstance: () => chartInstance,
  };
}

export { useEcharts };

export type { EchartsUIType };

这段 TypeScript 代码定义了一个名为 useEcharts 的自定义钩子函数,用于在 Vue 项目中集成和管理 ECharts 图表。下面是对代码详细的解释:

导入模块

import type { EChartsOption } from 'echarts'; // 导入 ECharts 选项类型
import type { Ref } from 'vue'; // 导入 Vue 的 Ref 类型
import type { Nullable } from '@vben/types'; // 导入可空类型
import type EchartsUI from './echarts-ui.vue'; // 导入 EchartsUI 组件类型

import { computed, nextTick, watch } from 'vue'; // 导入 Vue 的计算属性、下一个 DOM 更新周期方法和监听器
import { usePreferences } from '@vben/preferences'; // 导入偏好设置钩子
import {
  tryOnUnmounted,
  useDebounceFn,
  useResizeObserver,
  useTimeoutFn,
  useWindowSize,
} from '@vueuse/core'; // 导入 VueUse 核心库的一些钩子
import echarts from './echarts'; // 导入 ECharts 库
  • 类型导入:从不同的库中导入了所需的类型,包括 ECharts 选项类型、Vue 的 Ref 类型、可空类型以及 EchartsUI 组件类型。
  • 功能导入:从 vue 中导入了 computednextTickwatch 等功能,从 @vben/preferences 中导入了偏好设置钩子,从 @vueuse/core 中导入了一些实用的钩子,最后导入了 ECharts 库。

类型定义

type EchartsUIType = typeof EchartsUI | undefined; // 定义 EchartsUI 组件类型
type EchartsThemeType = 'dark' | 'light' | null; // 定义 ECharts 主题类型
  • EchartsUIType:表示 EchartsUI 组件类型,可能为 undefined
  • EchartsThemeType:表示 ECharts 的主题类型,有 'dark''light'null 三种可能。

useEcharts 函数

function useEcharts(chartRef: Ref<EchartsUIType>) {
  let chartInstance: echarts.ECharts | null = null; // 初始化 ECharts 实例
  let cacheOptions: EChartsOption = {}; // 初始化缓存的 ECharts 选项

  const { isDark } = usePreferences(); // 获取是否为深色模式
  const { height, width } = useWindowSize(); // 获取窗口的高度和宽度
  const resizeHandler: () => void = useDebounceFn(resize, 200); // 创建防抖的 resize 处理函数

  const getOptions = computed((): EChartsOption => {
    if (!isDark.value) {
      return {};
    }

    return {
      backgroundColor: 'transparent',
    };
  }); // 计算根据深色模式的 ECharts 选项
  • 变量初始化
    • chartInstance:用于存储 ECharts 实例,初始值为 null
    • cacheOptions:用于缓存 ECharts 选项,初始值为空对象。
  • 状态获取
    • isDark:通过 usePreferences 钩子获取当前是否为深色模式。
    • heightwidth:通过 useWindowSize 钩子获取窗口的高度和宽度。
  • 防抖处理:使用 useDebounceFn 创建一个防抖的 resize 处理函数,防抖时间为 200 毫秒。
  • 计算属性getOptions 是一个计算属性,根据 isDark 的值返回不同的 ECharts 选项。如果是深色模式,返回一个包含透明背景色的选项;否则返回空对象。

初始化 ECharts 实例

  const initCharts = (t?: EchartsThemeType) => {
    const el = chartRef?.value?.$el;
    if (!el) {
      return;
    }
    chartInstance = echarts.init(el, t || isDark.value ? 'dark' : null);

    return chartInstance;
  }; // 初始化 ECharts 实例
  • initCharts 函数用于初始化 ECharts 实例。它首先获取 chartRef 对应的 DOM 元素,如果元素不存在则直接返回。然后使用 echarts.init 方法初始化 ECharts 实例,并根据传入的主题或当前的深色模式设置主题。最后返回初始化后的实例。

渲染 ECharts 图表

  const renderEcharts = (
    options: EChartsOption,
    clear = true,
  ): Promise<Nullable<echarts.ECharts>> => {
    cacheOptions = options;
    const currentOptions = {
      ...options,
      ...getOptions.value,
    };
    return new Promise((resolve) => {
      if (chartRef.value?.offsetHeight === 0) {
        useTimeoutFn(async () => {
          resolve(await renderEcharts(currentOptions));
        }, 30);
        return;
      }
      nextTick(() => {
        useTimeoutFn(() => {
          if (!chartInstance) {
            const instance = initCharts();
            if (!instance) return;
          }
          clear && chartInstance?.clear();
          chartInstance?.setOption(currentOptions);
          resolve(chartInstance);
        }, 30);
      });
    });
  }; // 渲染 ECharts 图表
  • renderEcharts 函数用于渲染 ECharts 图表。它接收两个参数:options 表示要渲染的 ECharts 选项,clear 表示是否清除之前的图表内容,默认为 true
  • 函数首先将传入的 options 缓存到 cacheOptions 中,然后合并 optionsgetOptions 的值得到 currentOptions
  • 如果 chartRef 的高度为 0,说明图表容器还未完全渲染,使用 useTimeoutFn 延迟 30 毫秒后再次调用 renderEcharts 函数。
  • 否则,在 nextTick 中使用 useTimeoutFn 延迟 30 毫秒后进行图表的渲染。如果 chartInstance 不存在,则调用 initCharts 函数初始化实例。然后根据 clear 的值决定是否清除之前的图表内容,并使用 setOption 方法设置新的选项。最后通过 resolve 返回 chartInstance

调整 ECharts 图表大小

  function resize() {
    chartInstance?.resize({
      animation: {
        duration: 300,
        easing: 'quadraticIn',
      },
    });
  } // 调整 ECharts 图表大小
  • resize 函数用于调整 ECharts 图表的大小。它调用 chartInstanceresize 方法,并设置了一个动画效果,动画持续时间为 300 毫秒,缓动函数为 'quadraticIn'

监听事件

  watch([width, height], () => {
    resizeHandler?.();
  }); // 监听窗口大小变化,调用 resize 处理函数

  useResizeObserver(chartRef as never, resizeHandler); // 监听图表容器大小变化,调用 resize 处理函数

  watch(isDark, () => {
    if (chartInstance) {
      chartInstance.dispose();
      initCharts();
      renderEcharts(cacheOptions);
      resize();
    }
  }); // 监听深色模式变化,重新初始化和渲染图表
  • 窗口大小监听:使用 watch 监听 widthheight 的变化,当窗口大小改变时,调用防抖的 resizeHandler 函数。
  • 容器大小监听:使用 useResizeObserver 监听 chartRef 对应的 DOM 元素的大小变化,当容器大小改变时,调用 resizeHandler 函数。
  • 深色模式监听:使用 watch 监听 isDark 的变化,当深色模式改变时,销毁当前的 chartInstance,重新初始化 ECharts 实例,渲染缓存的选项,并调整图表大小。

组件卸载处理

  tryOnUnmounted(() => {
    // 销毁实例,释放资源
    chartInstance?.dispose();
  }); // 在组件卸载时销毁 ECharts 实例
  • 使用 tryOnUnmounted 钩子,在组件卸载时销毁 chartInstance,释放资源。

导出

  return {
    renderEcharts,
    resize,
    getChartInstance: () => chartInstance,
  };
}

export { useEcharts }; // 导出 useEcharts 钩子
export type { EchartsUIType }; // 导出 EchartsUIType 类型
  • useEcharts 函数返回一个对象,包含 renderEchartsresizegetChartInstance 三个方法。
  • 最后导出 useEcharts 钩子和 EchartsUIType 类型,供其他组件使用。

综上所述,这段代码通过自定义钩子 useEcharts 封装了 ECharts 的初始化、渲染、大小调整和主题切换等功能,方便在 Vue 项目中使用 ECharts 图表。同时,通过监听窗口和容器大小变化以及深色模式的改变,实现了图表的自适应和动态更新。

第一章 代码整体概述

1.1 代码功能简介

1.1.1 代码核心功能

此代码定义了一个名为 useEcharts 的自定义钩子,这个钩子就像是一个神奇的小助手‍♂️,专门用于在 Vue 项目中管理 ECharts 图表的各种操作:

  • 初始化:就像为一场演出搭建舞台一样,它会为 ECharts 图表准备好初始的环境和设置,让图表能够顺利“登场”。
  • 渲染:把数据转化为直观的图表,就如同画家把颜料变成美丽的画作,让用户能够清晰地看到数据的展示效果。
  • 调整大小:当页面大小发生变化时,它能像一个灵活的舞者一样,自动调整图表的大小,保证图表在不同的屏幕尺寸下都能完美呈现。
  • 深色模式适配:随着用户在浅色和深色模式之间切换,它能像一个智能的调光师一样,让图表的颜色和样式也随之改变,提供更好的视觉体验。
1.1.2 代码使用场景

这个代码适用于需要在 Vue 组件中集成 ECharts 图表,并且有以下需求的场景:

  • 响应式调整图表大小:比如在不同尺寸的设备上浏览网页,或者用户手动调整浏览器窗口大小时,图表能够自适应调整大小,始终保持良好的显示效果。
  • 支持深色模式切换:现在很多应用都提供了深色模式,当用户切换到深色模式时,图表也能相应地调整颜色和样式,避免在深色背景下看不清图表内容。

1.2 代码结构概述

1.2.1 导入模块

代码中导入了各种模块,这些模块就像是不同的工具,共同协作完成代码的功能:

  • ECharts 相关类型:这些类型就像是说明书,告诉代码如何正确地使用 ECharts 的各种功能和数据结构。
  • Vue 相关模块:为代码提供了 Vue 框架的支持,让代码能够与 Vue 组件完美结合,实现数据的响应式更新和组件的生命周期管理️。
  • 自定义偏好设置钩子:可以根据用户的个性化设置,对图表进行相应的调整,比如用户可能有自己喜欢的图表颜色、字体等。
  • VueUse 核心库的钩子:VueUse 是一个非常实用的工具库,其钩子可以帮助代码更方便地实现一些常见的功能,比如监听窗口大小变化等️‍♂️。
1.2.2 类型定义

定义了 EchartsUITypeEchartsThemeType 类型,它们的作用和用途如下:

  • EchartsUIType:就像是一个分类标签️,用于对 ECharts 图表的 UI 样式进行分类和定义,让代码能够更清晰地管理和使用不同的 UI 样式。
  • EchartsThemeType:类似于一个主题模板,用于定义 ECharts 图表的主题,比如浅色主题、深色主题等,方便在不同的主题之间进行切换。
1.2.3 钩子函数主体

useEcharts 函数的整体结构和主要逻辑流程就像是一场精心策划的演出:

  • 初始化阶段:准备好各种必要的参数和设置,就像演员们在后台化妆、换装,为演出做好准备。
  • 渲染阶段:根据传入的数据和设置,将图表渲染到页面上,就像演员们在舞台上精彩表演,展示出最终的效果。
  • 监听阶段:持续监听页面大小变化和深色模式切换等事件,一旦有变化就及时调整图表,就像舞台工作人员时刻关注着舞台的情况,及时调整灯光、道具等。
1.2.4 导出内容

导出的 useEcharts 钩子和 EchartsUIType 类型有着重要的作用:

  • useEcharts 钩子:就像是一个可以复用的工具包️,其他 Vue 组件可以通过导入这个钩子,轻松地在自己的组件中集成 ECharts 图表,并使用其提供的各种功能。
  • EchartsUIType 类型:为其他代码提供了一个统一的 UI 样式分类标准,方便不同的组件在使用 ECharts 图表时,能够遵循相同的 UI 规范,保持整体的一致性。

第二章 导入模块详解

2.1 ECharts 相关导入

2.1.1 EChartsOption 类型导入

1. 作用解释

EChartsOption 类型就像是一份严格的“设计蓝图”,它是 ECharts 配置选项的类型定义。在我们使用 ECharts 绘制图表时,需要传入一个配置对象来告诉 ECharts 我们想要绘制什么样的图表,比如图表的类型(柱状图、折线图等)、数据内容、样式设置等。而 EChartsOption 类型的存在,就是为了规范这个传入的配置对象。

它可以帮助我们在编写代码时,提前发现配置对象中可能存在的错误,比如属性名拼写错误、属性类型不匹配等。就好比在建造房子之前,先有一份详细准确的蓝图,这样在施工过程中就能避免很多不必要的错误和麻烦。

例如,在 TypeScript 中使用 ECharts 时,如果我们定义一个配置对象并指定其类型为 EChartsOption

import { EChartsOption } from 'echarts';

const option: EChartsOption = {
    xAxis: {
        type: 'category',
        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    },
    yAxis: {
        type: 'value'
    },
    series: [{
        data: [820, 932, 901, 934, 1290, 1330, 1320],
        type: 'line'
    }]
};

这样,当我们写错属性名或者属性类型不匹配时,编译器就会及时给我们报错提示。

2.1.2 echarts 库导入

1. 导入目的

导入 echarts 库就像是打开了一个功能强大的“工具箱”,我们可以使用这个工具箱里的各种工具来完成 ECharts 的初始化、渲染等功能。

ECharts 库提供了一系列的方法和属性,让我们能够方便地创建和操作图表。比如,我们可以使用 echarts.init 方法来初始化一个 ECharts 实例,然后使用 setOption 方法将配置对象应用到这个实例上,从而实现图表的渲染。

示例代码如下:

import * as echarts from 'echarts';

// 初始化 ECharts 实例
const myChart = echarts.init(document.getElementById('main'));

// 设置配置项并渲染图表
const option = {
    // 配置项内容
};
myChart.setOption(option);

通过导入 echarts 库,我们就可以利用这些功能轻松地在网页上绘制出各种精美的图表。

2.2 Vue 相关导入

2.2.2.1 Ref 类型导入

1. 作用解释

在 Vue 中,Ref 类型就像是一个“魔法盒子”,用于创建响应式引用。它可以让我们在代码中方便地引用某个值,并且当这个值发生变化时,与之关联的 DOM 元素或者其他依赖项会自动更新。

在我们的代码中,Ref 类型主要用于引用 EchartsUI 组件。通过 Ref,我们可以获取到 EchartsUI 组件的实例,进而对其进行操作。

例如:




这样,我们就可以通过 echartsRef.value 来访问 EchartsUI 组件的实例,调用其方法或者获取其属性。

2.2.2 computednextTickwatch 导入

1. computed 的作用

computed 就像是一个“智能计算器”,用于创建计算属性。计算属性是根据其他数据动态计算得出的属性,它会根据依赖的数据自动更新。

当我们有一些数据需要根据其他数据进行计算时,使用计算属性可以让代码更加简洁和易于维护。例如:




在这个例子中,doubleNum 就是一个计算属性,它的值会根据 num 的变化而自动更新。

2. nextTick 的作用

nextTick 就像是一个“时间旅行者”️‍♂️,用于在 DOM 更新后执行回调。在 Vue 中,数据的更新是异步的,当我们修改数据后,DOM 不会立即更新。而 nextTick 可以让我们在 DOM 更新完成后再执行一些操作。

例如,当我们需要获取更新后的 DOM 元素的尺寸或者位置时,就可以使用 nextTick




这样,我们就可以确保在 DOM 更新完成后再执行相应的操作。

3. watch 的作用

watch 就像是一个“监控摄像头”,用于监听数据变化并执行相应操作。当我们需要在某个数据发生变化时执行一些特定的逻辑时,就可以使用 watch

例如:




在这个例子中,当 inputValue 的值发生变化时,watch 会自动触发回调函数,我们可以在回调函数中执行相应的操作。

2.3 自定义模块导入

2.3.1 usePreferences 导入

1. 作用解释

usePreferences 钩子就像是一个“个人秘书”,用于获取用户的偏好设置。在我们的代码中,主要用于判断用户是否选择了深色模式。

用户的偏好设置可能包括主题模式、字体大小、语言等,通过 usePreferences 钩子,我们可以方便地获取这些设置,并根据用户的偏好来调整页面的显示效果。

例如:




这样,我们就可以根据 isDarkMode 的值来动态添加或移除 dark-mode 类,从而实现深色模式的切换。

2.3.2 EchartsUI 组件导入

1. 导入目的

导入 EchartsUI 组件就像是为图表找到了一个“家”,其目的是为了获取图表容器的 DOM 元素。

EchartsUI 组件通常是一个包含图表容器的组件,我们通过导入这个组件并在页面中使用它,就可以获取到这个容器的 DOM 元素,然后在这个容器中初始化和渲染 ECharts 图表。

例如:




这样,我们就可以通过 chartContainer.value 来获取图表容器的 DOM 元素,进而在这个元素上初始化 ECharts 实例。

2.4 VueUse 核心库导入

2.4.1 tryOnUnmounted 导入

1. 作用解释

tryOnUnmounted 就像是一个“清洁工”,用于在组件卸载时执行清理操作。在我们的代码中,主要用于销毁 ECharts 实例。

当一个组件被卸载时,如果不及时清理一些资源,可能会导致内存泄漏等问题。而 tryOnUnmounted 可以确保在组件卸载时,我们能够执行一些必要的清理操作,比如销毁 ECharts 实例。

例如:




这样,当组件被卸载时,就会自动执行销毁 ECharts 实例的操作,避免资源的浪费。

2.4.2 useDebounceFn 导入

1. 用途说明

useDebounceFn 就像是一个“节流阀”,通过防抖处理减少 resize 函数的调用频率,提高性能。

当我们监听元素的大小变化时,比如窗口大小变化或者图表容器大小变化,resize 事件可能会频繁触发。如果每次触发都执行 resize 函数,会导致性能问题。而 useDebounceFn 可以让 resize 函数在一段时间内只执行一次,避免不必要的性能开销。

例如:




在这个例子中,useDebounceFn 会让 handleResize 函数在 300 毫秒内只执行一次,从而减少了函数的调用频率,提高了性能。

2.4.3 useResizeObserver 导入

1. 作用解释

useResizeObserver 就像是一个“尺寸侦探”️,用于监听元素大小变化。在我们的代码中,主要用于监听图表容器的大小变化并调用 resize 函数。

当图表容器的大小发生变化时,我们需要及时调整图表的大小,以保证图表能够正确显示。useResizeObserver 可以帮助我们实时监测图表容器的大小变化,一旦发生变化,就会触发相应的回调函数,我们可以在回调函数中调用 resize 函数来调整图表的大小。

例如:




这样,当图表容器的大小发生变化时,就会自动调用 resize 函数来调整图表的大小,保证图表的显示效果。

2.4.4 useTimeoutFn 导入

1. 用途说明

useTimeoutFn 就像是一个“定时闹钟”⏰,用于在指定时间后执行回调函数。在代码中用于处理图表渲染时的延迟操作。

有时候,我们需要在图表渲染之前或者之后执行一些延迟操作,比如等待数据加载完成后再渲染图表,或者在图表渲染完成后执行一些动画效果。useTimeoutFn 可以帮助我们实现这些延迟操作。

例如:




这样,就可以在 1000 毫秒后执行图表渲染的逻辑,实现延迟操作。

2.4.5 useWindowSize 导入

1. 作用解释

useWindowSize 就像是一个“窗口测量员”,用于获取窗口的高度和宽度,以便在窗口大小变化时调整图表大小。

当窗口大小发生变化时,图表的大小也需要相应地调整,以保证图表能够适应不同的窗口尺寸。useWindowSize 可以实时获取窗口的高度和宽度,我们可以根据这些信息来动态调整图表的大小。

例如:




这样,当窗口大小发生变化时,就可以根据新的窗口高度和宽度来调整图表的大小,保证图表的显示效果。

第三章 类型定义详解

3.1 EchartsUIType 类型

3.1.1 类型定义

EchartsUIType 被定义为 typeof EchartsUI | undefined ,这到底是什么意思呢?

  • typeof EchartsUI:这里的 typeof 是一个操作符,它会返回 EchartsUI 的类型。也就是说,它代表的是 EchartsUI 这个组件本身所具有的类型。想象一下,EchartsUI 就像是一个独特的“物品”,而 typeof EchartsUI 就是描述这个“物品”特征的标签️。
  • | undefined:这个 | 符号在类型定义里表示“或”的关系。undefined 是 JavaScript 中的一个原始值,表示变量已声明但未赋值,或者函数没有返回值。所以 | undefined 意味着 EchartsUIType 除了可以是 EchartsUI 的类型,还可以是未定义的情况。就好比一个盒子,里面要么装着 EchartsUI 这个“物品”,要么就是空的(未定义)。

综上所述,EchartsUIType 表示的就是 EchartsUI 组件的类型或者未定义的情况。

3.1.2 用途

这个类型在代码中主要用于 chartRef 的类型定义,这是为什么呢?

在 React 等框架中,ref 是一种用来引用 DOM 节点或者组件实例的方式。chartRef 就是用来引用 EchartsUI 组件的一个引用对象。通过将 chartRef 的类型定义为 EchartsUIType,可以确保我们引用的是 EchartsUI 组件。

举个例子,如果我们不小心把 chartRef 引用到了其他类型的组件或者变量上,由于类型不匹配,编译器就会发出警告⚠️,这样就能避免一些潜在的错误。就好像我们给一个特定的“停车位”(chartRef)设置了只能停放“EchartsUI 汽车”的规则,一旦有其他“车辆”试图停进去,就会被阻止。

3.2 EchartsThemeType 类型

3.2.1 类型定义

EchartsThemeType 被定义为 'dark' | 'light' | null ,下面来详细解释一下。

  • 'dark''light':ECharts 是一个强大的可视化库,它支持不同的主题,其中 'dark' 代表深色主题,'light' 代表浅色主题。这就好比我们可以给一幅画选择不同的背景颜色,深色背景会让画面显得神秘、沉稳,浅色背景则会让画面更加明亮、清新。
  • null:在 JavaScript 中,null 表示一个空对象指针。在这里,null 表示不指定任何主题。就好像我们选择不给画设置背景颜色,让它保持默认的样子️。

所以,EchartsThemeType 表示的就是 ECharts 支持的主题类型。

3.2.2 用途

这个类型在代码中的主要使用场景是在 initCharts 函数中指定 ECharts 实例的主题。

initCharts 函数的作用是初始化一个 ECharts 实例,在初始化的过程中,我们可以通过传入 EchartsThemeType 类型的参数来指定使用的主题。例如:

function initCharts(theme: EchartsThemeType) {
    // 初始化 ECharts 实例
    const myChart = echarts.init(dom, theme);
    // 其他初始化操作
    // ...
}

通过这种方式,我们可以根据不同的需求灵活地选择 ECharts 实例的主题。如果我们想要一个深色主题的图表,就可以调用 initCharts('dark');如果想要浅色主题,就调用 initCharts('light');如果不想指定主题,就调用 initCharts(null)。这样可以让我们的图表在不同的场景下都能呈现出最佳的视觉效果。

第四章 useEcharts 钩子函数详解

4.1 变量初始化

4.1.1 chartInstance 变量

chartInstance 变量在 useEcharts 钩子函数中扮演着至关重要的角色。它的主要作用是存储 ECharts 实例。想象一下,ECharts 实例就像是一个功能强大的“魔法盒子”,里面包含了图表的各种属性和方法。通过将这个“魔法盒子”存储在 chartInstance 变量中,我们就可以在后续的代码里轻松地对图表进行各种操作,比如渲染图表,让它在页面上显示出来;或者调整图表的大小,使它能够完美适配不同的屏幕尺寸。

4.1.2 cacheOptions 变量

cacheOptions 变量就像是一个“仓库”,它的用途是缓存传入的 ECharts 配置选项。在实际开发中,我们可能会根据不同的条件或者用户的操作来重新渲染图表。这时候,就可以从 cacheOptions 这个“仓库”里取出之前存储的配置选项,然后用这些选项来重新渲染图表,避免了重复传递配置选项的麻烦,提高了代码的效率和可维护性。

4.2 响应式数据获取

4.2.1 isDark 获取

通过 usePreferences 钩子来获取 isDark 变量,这就像是给我们的代码装上了一个“模式探测器”️。isDark 变量用于判断当前是否处于深色模式。在不同的模式下,图表的显示效果可能会有所不同,比如在深色模式下,我们可能需要调整图表的背景颜色、字体颜色等配置,让图表在深色背景下也能清晰地显示出来。所以,获取 isDark 变量可以帮助我们根据当前的模式动态地调整图表的配置。

4.2.2 widthheight 获取

使用 useWindowSize 钩子来获取窗口的宽度和高度,就像是给我们的图表安装了一个“尺寸追踪器”。在现代的网页设计中,页面需要能够自适应不同的屏幕尺寸。当用户调整浏览器窗口的大小时,图表也需要相应地调整大小,以保证良好的用户体验。通过获取窗口的宽度和高度,我们可以监听窗口大小的变化,并在变化发生时调用相应的函数来调整图表的大小,让图表始终与窗口大小保持一致。

4.3 防抖处理

4.3.1 resizeHandler 函数

resizeHandler 函数是通过 useDebounceFnresize 函数进行防抖处理后的函数。想象一下,当用户频繁地调整窗口大小时,如果每次窗口大小发生微小的变化都立即调用 resize 函数来调整图表大小,那么会导致 resize 函数被频繁调用,这不仅会消耗大量的性能,还可能会让图表的调整效果变得不流畅。而 resizeHandler 函数就像是一个“缓冲器”,它会在用户停止调整窗口大小一段时间后才调用 resize 函数,减少了 resize 函数的调用频率,提高了性能,让图表的调整更加平滑。

4.4 计算属性 getOptions

4.4.1 计算逻辑

getOptions 计算属性的计算逻辑就像是一个“智能转换器”。它会根据 isDark 的值来返回不同的 ECharts 配置选项。当 isDarktrue,也就是处于深色模式时,它会将图表的背景颜色设置为透明,这样可以让图表更好地融入深色背景中。而当 isDarkfalse 时,它会返回默认的配置选项。

4.4.2 用途

这个计算属性在代码中的使用场景就像是一个“拼图块”。它主要用于合并到最终的 ECharts 配置选项中。在渲染图表时,我们需要将各种配置选项组合在一起,而 getOptions 计算属性提供了根据不同模式动态生成的配置选项,将它合并到最终的配置中,就可以让图表根据当前的模式进行正确的渲染。

4.5 initCharts 函数

4.5.1 函数功能

initCharts 函数的主要功能是初始化 ECharts 实例,就像是给图表“搭建一个家”。它会根据传入的主题类型或者当前的深色模式来设置图表的主题。不同的主题可以让图表呈现出不同的风格,比如明亮的风格或者深色的风格,以满足不同用户的需求。

4.5.2 实现细节

在函数内部,首先需要获取图表容器的 DOM 元素,这就像是找到图表“家”的具体位置。通常会使用 document.getElementById 或者 ref 等方式来获取 DOM 元素。然后,调用 echarts.init 方法,传入图表容器的 DOM 元素和主题类型,就可以初始化一个 ECharts 实例,将这个实例存储在 chartInstance 变量中,方便后续的操作。

4.6 renderEcharts 函数

4.6.1 函数功能

renderEcharts 函数的主要功能是渲染 ECharts 图表,就像是给图表“穿上漂亮的衣服”。它会处理一些特殊情况,比如图表容器高度为 0 的情况,这时候可能需要等待容器高度正常后再进行渲染。同时,它会在 DOM 更新后进行渲染操作,确保图表能够正确地显示在页面上。

4.6.2 实现细节

在函数内部,首先会合并配置选项,将 cacheOptionsgetOptions 等配置选项组合在一起,形成最终的配置。然后,会处理延迟渲染的情况,比如使用 nextTick 等方法确保在 DOM 更新后再进行渲染。接着,会清除之前的图表,避免出现重叠或者显示异常的问题。最后,调用 chartInstance.setOption 方法,将最终的配置选项设置到 ECharts 实例中,完成图表的渲染。

4.6.3 返回值

函数返回的 Promise 对象就像是一个“承诺使者”。它在图表渲染完成后返回 ECharts 实例。我们可以通过 then 方法来处理这个返回的实例,比如在图表渲染完成后进行一些额外的操作,如添加事件监听器等。

4.7 resize 函数

4.7.1 函数功能

resize 函数的作用是调整 ECharts 实例的大小,就像是给图表“量身定制衣服”。它还设置了动画效果,让图表在调整大小时能够平滑地过渡,给用户带来更好的视觉体验。

4.7.2 实现细节

在函数内部,会调用 chartInstance.resize 方法,传入一些配置参数,如动画效果的配置等,来实现图表大小的调整。通过这个方法,ECharts 实例会根据新的大小重新计算和绘制图表,让图表适应新的尺寸。

4.8 监听器

4.8.1 窗口大小变化监听

watch([width, height], () => { resizeHandler?.(); }) 就像是一个“窗口变化哨兵”。当窗口的宽度或者高度发生变化时,它会触发回调函数,调用 resizeHandler 函数进行图表大小的调整。这样,无论用户如何调整窗口大小,图表都能及时地做出响应,保持良好的显示效果。

4.8.2 图表容器大小变化监听

useResizeObserver(chartRef as never, resizeHandler) 就像是一个“容器变化侦探”️‍♂️。它会监听图表容器的大小变化,当容器的大小发生改变时,会调用 resizeHandler 函数进行图表大小的调整。这对于一些动态改变容器大小的场景非常有用,比如在页面布局发生变化时,图表能够自动调整大小。

4.8.3 深色模式变化监听

watch(isDark, () => { ... }) 就像是一个“模式变化警报器”。当深色模式发生变化时,它会触发回调函数。在回调函数中,会销毁当前的 ECharts 实例,就像是拆除旧的“房子”,然后重新初始化并渲染图表,给图表换上适应新模式的“衣服”,让图表在不同的模式下都能正常显示。

4.9 组件卸载处理

4.9.1 tryOnUnmounted 函数

tryOnUnmounted 函数的作用是在组件卸载时销毁 ECharts 实例,就像是在离开“房子”时关闭所有的电器设备,释放资源⚡。如果不销毁 ECharts 实例,它会一直占用内存,可能会导致内存泄漏,影响页面的性能。通过在组件卸载时销毁实例,可以避免这种问题,让页面更加稳定和高效。

4.10 返回值

4.10.1 返回对象的属性

返回对象中包含了 renderEchartsresizegetChartInstance 方法。

  • renderEcharts 方法就像是一个“渲染大师”,用于渲染图表,将配置选项应用到图表上,让图表显示在页面上。
  • resize 方法就像是一个“尺寸调整师”,用于调整图表的大小,让图表适应不同的屏幕尺寸。
  • getChartInstance 方法就像是一个“实例获取员”‍,用于获取 ECharts 实例,方便在其他地方对图表进行进一步的操作。通过返回这些方法,外部组件可以方便地使用 useEcharts 钩子提供的功能,实现图表的渲染、调整等操作。

第五章 导出内容详解

5.1 useEcharts 钩子导出

5.1.1 导出目的

在开发 Vue 项目时,我们经常会使用 ECharts 库来创建各种精美的图表。为了更方便地在不同的 Vue 组件中管理和使用 ECharts 图表,我们将 useEcharts 钩子导出。这个钩子封装了与 ECharts 相关的一些通用逻辑,比如图表的初始化、数据更新、事件绑定等。通过导出这个钩子,其他 Vue 组件可以直接引入并使用它,避免了在每个组件中重复编写相同的 ECharts 管理代码,提高了代码的复用性和可维护性。

5.1.2 使用方式

以下是在其他组件中使用 useEcharts 钩子的详细步骤:

  1. 引入钩子
    在需要使用 useEcharts 钩子的 Vue 组件中,首先要引入它。假设 useEcharts 钩子定义在 hooks/useEcharts.js 文件中,引入代码如下:
import { useEcharts } from '@/hooks/useEcharts';
  1. 在组件中调用
    在组件的 setup 函数中调用 useEcharts 钩子,并根据需要进行配置。示例代码如下:



在上述代码中,我们首先创建了一个 chartRef 用于引用图表的容器元素。然后调用 useEcharts 钩子,并传入 chartRef。最后,调用 initChart 方法并传入 ECharts 的配置项来初始化图表。

5.2 EchartsUIType 类型导出

5.2.2 使用方式

5.2.1 导出目的

在 TypeScript 项目中,类型定义非常重要,它可以帮助我们在开发过程中更早地发现类型错误,提高代码的健壮性。EchartsUIType 类型是对 ECharts 相关 UI 元素的类型定义,比如图表的配置项、样式等。通过导出 EchartsUIType 类型,其他模块可以直接引用这个类型,确保在使用 ECharts 相关数据时类型的一致性和准确性。

5.2.2 使用方式

以下是在其他模块中使用 EchartsUIType 类型的详细步骤:

  1. 引入类型
    在需要使用 EchartsUIType 类型的模块中,首先要引入它。假设 EchartsUIType 类型定义在 types/EchartsUIType.ts 文件中,引入代码如下:
import { EchartsUIType } from '@/types/EchartsUIType';
  1. 在类型注解中引用该类型
    在代码中需要使用 ECharts 相关数据的地方,可以使用 EchartsUIType 类型进行类型注解。示例代码如下:
import { EchartsUIType } from '@/types/EchartsUIType';

function updateChartConfig(config: EchartsUIType): void {
  // 在这里可以对图表配置进行更新操作
  console.log('Updating chart config:', config);
}

const chartConfig: EchartsUIType = {
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      data: [120, 200, 150, 80, 70, 110, 130],
      type: 'bar'
    }
  ]
};

updateChartConfig(chartConfig);

在上述代码中,我们定义了一个 updateChartConfig 函数,它接受一个 EchartsUIType 类型的参数。然后创建了一个 chartConfig 对象,并将其类型注解为 EchartsUIType。最后调用 updateChartConfig 函数并传入 chartConfig,这样可以确保传入的参数类型符合要求。

你可能感兴趣的:(Vben3项目知识总结,Vben3,源码解读,vue.js,前端,javascript)