Vue3 + hook + Apexcharts实现可视化图表渲染的封装 - 第一节 - 基础封装

目录

Vue3 + hook + Apexcharts实现可视化图表渲染的封装 - 第一节 - 基础封装 (当前所在)
Vue3 + hook + Apexcharts实现可视化图表渲染的封装 - 第二节 - 图表的全屏功能(Vuex)

摘要

可视化是切图仔的必备技能,大部分需求我都是通过现有工具,不必自己实现。比如 EchartsD3Antv 等可视化工具,但是我们今天的主角都是这些,是一个叫 Apexcharts 的可视化工具。Apexchartsjs+svg 实现的(ps: Echarts 同时支持 canvassvg 渲染图表)。
因为工作偶然接触到 Apexcharts ,但是该工具的社区环境是真的差,如果遇到什么问题在网上基本上搜不到信息,只有官方文档。这里对开发使用过程的封装进行整理保存,后续针对其他的问题进行整理。

官方文档纯英文
中文文档非官方

正文

安装
npm i -D apexcharts
npm i -D vue3-apexcharts
基础使用

基础使用具体请查看 vue3-apexcharts 文档,

<template>
  <div>
    <ApexChart
      width="500"
      type="bar"
      :options="chartOptions"
      :series="series"
    />
  </div>
</template>

<script setup>
import ApexChart from 'vue3-apexcharts'

const chartOptions =  {
   chart: {
     id: "vuechart-example",
   },
   xaxis: {
     categories: [1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998],
   },
},
const series = [
    {
      name: "series-1",
      data: [30, 40, 35, 50, 49, 60, 70, 91],
    },
],
</script>

在前端开发过程中图表的数据都是通过接口获取的,在数据更新后需要动态触发 Apexcharts 的更新,当我们在 ApexChart 中绑定一个ref时: <ApexChart ref="chartRef" /> ,可以通过 chartRef 访问图表的 DOM 元素,然后通过 chartRef.updateOptions(最新的数据) 函数去触发图表的重新渲染。注意:必须在 ApexChart DOM元素更新之后才能获取到 updateOptions 所以最好提前渲染一个数据为空的图表。如果无法获取,可以通过 nextTieck() 去渲染。

图表渲染的 hook 封装

当我们通过 v-for 去渲染多个 <Apexchart /> 时,我们可以通过动态创建 ref 正确绑定到对应的图表项中。下面直接放封装的hook

/*
**	useRenderChart.js
**	chartList 为传入的需要渲染的图表数组,具体格式见下面使用过程
*/
const useRenderChart = (chartList) => {
	// 对scatter数据进行做截取,如果
	const getScatterData = (data, intercept) => {
		const obj = {}
		Object.keys(data).forEach(key => {
			obj[key] = data[key].slice(0, intercept)
		})
		return obj
	}
	
	// 触发图表的重新渲染,chartObj.updateOptions(data)返回的是一个对象包含新的series|options
	const updateChart = (data, chartRef, chartObj) => {
		chartRef.updateOptions(chartObj.updateOptions(data))
	}

	// 统一渲染函数,触发所有图表的重新更新
	const renderCharts = (data) => {
		chartList.forEach(item => {
			const { key, refName, chartObj, intercept, type, interceptFn } = item
			item.data = data[key]
			let chartData = []
			if (type === 'scatter' && !interceptFn) {
				chartData = getScatterData(data[key], intercept)
			} else if (intercept) {
				chartData = interceptFn ? interceptFn(data[key], intercept) : data[key].slice(0, intercept)
			} else {
				chartData = data[key]
			}

			if (!chartData) return
			if (Array.isArray(chartData)) {
				chartData.length && updateChart(chartData, refName, chartObj)
			} else {
				updateChart(chartData, refName, chartObj)
			}
		})
	}

	// 动态设置图表的ref
	const setRefMap = (el, index) => {
		chartList[index].refName = el
	}

	return {
		getScatterData,
		renderCharts,
		setRefMap,
	}
}

export default useRenderChart

使用
<template>
	<div v-for="(item, index) in chartList" :key="item.key" :id="item.key" class="chart-item">
		<div class="title">{{ item.title }}</div>
		<ApexChart
			:ref="el => setRefMap(el, index)"
			:type="item.type"
			:options="item.chartObj.options"
			:series="item.chartObj.series"
		/>
	</div>
</template>

<script setup>
import ApexChart from 'vue3-apexcharts'
import { BoxPlotChart, KMChart } from '@/utils/chartsInit'
import useRenderChart from '@/hook/useRenderChart'

/**
 * 图表数据处理
 * @param {Array} chartList 需要渲染的图表列表
 * @param {Object} chartObj 图表对象 - 可做统一封装
 * @param {String} key 图表key,用于渲染图表时找到对应的数据
 * @param {String} title 图表标题
 * @param {String} type 图表类型
 * @param {Number} intercept 图表数据截取长度
 * @param {Function} interceptFn 自定义图表数据截取函数
 */
const chartList = reactive([
	{
		key: 'coef_data',
		title: 'Coefficient',
		type: 'boxPlot',
		chartObj: BoxPlotChart,
	},
	{
		key: 'train',
		title: 'KM plot (train)',
		type: 'line',
		chartObj: KMChart,
		intercept: 1000,
		interceptFn: (data, intercept) => {
			return data.map(item => {
				const obj = {}
				obj.prob = item.prob?.slice(0, intercept)
				obj.time = item.time?.slice(0, intercept)
				return obj
			})
		},
	},
])
const { renderCharts, setRefMap } = useRenderChart(chartList)

// 请求数据后触发图表重新渲染
async function handleGetData() {
	// ...
	// data数据一个对象{},包含chartList的每个key,对应值为图表的新数据
	renderCharts(data)
}

chartsInit.js 的图表封装,以上面的 BoxPlotChart 为例子

export const BoxPlotChart = {
	series: [],
	options: {
		xaxis: {
			type: 'category',
		},
		// ...
	},
	updateOptions: data => {
		return {
			series: [],
			xaxis: {},
			// ...等等options的配置
		}
	},
}

总结

对于上面的统一封装的 useRenderChart 这里去掉了 全屏查看图表功能 的,因为涉及到其他一部分逻辑,以及对上面所有代码的更改。将在下一篇文章补充实现。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3是一种用于构建用户界面的JavaScript框架,它具有快速、灵活、可重用等特点。Webpack则是一种JS的打包工具,可以将多个JS文件打成一个JS文件。Vue-Router是Vue框架中的路由管理器,通过它可以实现前端路由的切换。Axios则是一种基于Promise的 HTTP 库,用于处理前端与后端的数据交互。Vuex则是Vue框架中的状态管理工具,将组件的共享状态抽取出来,以集中管理,便于开发人员管理。这些技术都是前端开发中必不可少的技术,用于优化前端项目的结构,提高开发效率。 在具体的项目开发中,为了提高代码的复用性,通常会对这些技术进行进一步的封装。对于Vue-Router,可以将项目的路由进行封装,创建一个Route.js文件,用于统一管理路由。通过这样的封装,可以使得路由的管理更加清晰。 对于Axios,可以通过封装一个API.js文件,将后端接口进行统一管理,减少代码的重复性。在API.js中可以封装所有后端接口的请求方法,统一处理请求返回的数据。 对于Vuex,则可以将项目的状态进行封装,写一个store.js文件,用于集中管理应用的状态。在store.js中可以设置全局数据,方便在各个组件中进行访问和修改。同时,也可以将状态的变化通过mutations.js文件封装,以保证数据的可靠性。 最后,使用Webpack进行打包。Webpack可以将多个JS文件打成一个JS文件,减少了请求的次数,提高了页面的加载速度。 综上所述,通过对Vue3、Webpack、Vue-Router、Axios、Vuex等技术的封装,可以提高代码的复用性和可维护性,从而加快项目的开发进度。同时,这些技术的结合还能够为项目提供更好的架构,提升用户的使用体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值