vue3+vite+JS使用Echarts封装一个饼图完整代码(父子组件联动)

 更新时间:2026年03月13日 08:28:38   作者:还是大剑师兰特  
在Vue中绘制饼图有多种方式,其中最常用的是使用第三方图表库,如ECharts、Chart.js等,下面这篇文章主要介绍了vue3+vite+JS使用Echarts封装一个饼图(父子组件联动)的相关资料,需要的朋友可以参考下

前言

本文要在vue3+vite+JS项目中,使用Echarts封装一个饼图子组件,父组件中引入子组件并传入数据。传入的数据包括标题、高度、宽度、饼图数据,resize监听尺寸。子组件监听饼图数据的变化,来更新子组件的显示内容。

一、实现思路

  1. 子组件封装:基于 ECharts 封装饼图组件,接收父组件传入的标题、宽高、饼图数据等 props;
  2. 响应式处理:监听饼图数据变化,自动更新图表;监听窗口 resize 事件,自适应调整图表尺寸;
  3. 父组件使用:导入子组件,传入自定义数据,实现灵活配置。

二、完整代码实现

1. 安装 ECharts 依赖

npm install echarts --save
# 或 yarn add echarts

2. 饼图子组件(PieChart.vue)

<template>
  <!-- 图表容器,宽高由父组件传入 -->
  <div 
    ref="chartRef" 
    class="pie-chart-container"
    :style="{ width: width + 'px', height: height + 'px' }"
  ></div>
</template>

<script setup>
import { ref, watch, onMounted, onUnmounted } from 'vue'
import * as echarts from 'echarts'

// 定义接收的 props
const props = defineProps({
  // 饼图标题
  title: {
    type: String,
    default: '饼图示例'
  },
  // 图表宽度(px)
  width: {
    type: Number,
    default: 400
  },
  // 图表高度(px)
  height: {
    type: Number,
    default: 300
  },
  // 饼图数据(格式:[{ name: '分类1', value: 100 }, ...])
  chartData: {
    type: Array,
    required: true,
    validator: (val) => {
      // 简单校验数据格式
      return val.every(item => item.hasOwnProperty('name') && item.hasOwnProperty('value'))
    }
  }
})

// 图表实例引用
const chartRef = ref(null)
// ECharts 实例
let chartInstance = null

// 初始化图表
const initChart = () => {
  // 确保容器存在
  if (!chartRef.value) return
  
  // 初始化 ECharts 实例
  chartInstance = echarts.init(chartRef.value)
  
  // 设置图表配置项
  const option = {
    title: {
      text: props.title,
      left: 'center' // 标题居中
    },
    tooltip: {
      trigger: 'item', // 鼠标悬浮提示
      formatter: '{a} 
{b}: {c} ({d}%)' // 提示格式:名称:数值(百分比)
    },
    legend: {
      orient: 'vertical', // 图例垂直排列
      left: 'left' // 图例居左
    },
    series: [
      {
        name: props.title,
        type: 'pie',
        radius: ['40%', '70%'], // 饼图内外半径
        avoidLabelOverlap: false,
        label: {
          show: false,
          position: 'center'
        },
        emphasis: {
          label: {
            show: true,
            fontSize: 16,
            fontWeight: 'bold'
          }
        },
        labelLine: {
          show: false
        },
        data: props.chartData // 饼图数据
      }
    ]
  }
  
  // 渲染图表
  chartInstance.setOption(option)
}

// 更新图表(数据变化时调用)
const updateChart = () => {
  if (!chartInstance) return
  
  // 仅更新数据相关配置,避免重复初始化
  chartInstance.setOption({
    title: { text: props.title },
    series: [{ data: props.chartData }]
  })
}

// 监听窗口 resize,自适应调整图表尺寸
const handleResize = () => {
  if (chartInstance) {
    chartInstance.resize()
  }
}

// 生命周期:挂载时初始化图表 + 监听 resize
onMounted(() => {
  initChart()
  window.addEventListener('resize', handleResize)
})

// 生命周期:卸载时销毁实例 + 移除监听
onUnmounted(() => {
  if (chartInstance) {
    chartInstance.dispose() // 销毁 ECharts 实例,释放内存
    chartInstance = null
  }
  window.removeEventListener('resize', handleResize)
})

// 监听 props 变化,更新图表
watch(
  // 监听标题、宽高、数据的变化
  [() => props.title, () => props.width, () => props.height, () => props.chartData],
  () => {
    // 宽高变化时先销毁再重新初始化,数据/标题变化时仅更新配置
    if (props.width || props.height) {
      chartInstance?.dispose()
      initChart()
    } else {
      updateChart()
    }
  },
  {
    deep: true // 深度监听数组/对象变化
  }
)
</script>

<style scoped>
.pie-chart-container {
  /* 防止容器内边距影响尺寸 */
  box-sizing: border-box;
  /* 解决图表容器闪烁问题 */
  transition: all 0.3s ease;
}
</style>

3. 父组件(ParentPage.vue)

<template>
  <div class="parent-page">
    <h2>饼图组件使用示例</h2>
    
    <!-- 操作区:修改数据/尺寸 -->
    <div class="control-panel">
      <button @click="changeChartData">切换饼图数据</button>
      <button @click="changeChartSize">修改图表尺寸</button>
      <button @click="changeChartTitle">修改图表标题</button>
    </div>
    
    <!-- 引入饼图子组件,传入配置 -->
    <PieChart 
      :title="chartTitle"
      :width="chartWidth"
      :height="chartHeight"
      :chart-data="chartData"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
// 导入饼图子组件
import PieChart from './PieChart.vue'

// 定义饼图配置数据(响应式)
const chartTitle = ref('各部门人数分布')
const chartWidth = ref(500)
const chartHeight = ref(400)

// 初始饼图数据
const chartData = ref([
  { name: '技术部', value: 30 },
  { name: '产品部', value: 15 },
  { name: '市场部', value: 20 },
  { name: '财务部', value: 8 },
  { name: '人事部', value: 7 }
])

// 模拟:切换饼图数据
const changeChartData = () => {
  chartData.value = [
    { name: '技术部', value: 40 },
    { name: '产品部', value: 10 },
    { name: '市场部', value: 25 },
    { name: '财务部', value: 5 },
    { name: '人事部', value: 10 },
    { name: '运营部', value: 10 } // 新增分类
  ]
}

// 模拟:修改图表尺寸
const changeChartSize = () => {
  chartWidth.value = 600
  chartHeight.value = 450
}

// 模拟:修改图表标题
const changeChartTitle = () => {
  chartTitle.value = '各部门人数分布(更新后)'
}
</script>

<style scoped>
.parent-page {
  padding: 20px;
}

.control-panel {
  margin-bottom: 20px;
}

.control-panel button {
  margin-right: 10px;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  background: #409eff;
  color: #fff;
  cursor: pointer;
}

.control-panel button:hover {
  background: #66b1ff;
}
</style>

三、关键代码解释

  1. 子组件核心逻辑

    • props 定义:明确接收标题、宽高、饼图数据,且对 chartData 做格式校验,确保数据合法性;
    • 图表初始化initChart 方法创建 ECharts 实例并配置基础样式,updateChart 方法仅更新数据/标题,避免重复初始化;
    • 响应式监听:通过 watch 深度监听 props 变化,宽高变化时重新初始化图表,数据/标题变化时仅更新配置;
    • 生命周期管理onMounted 时初始化图表并添加 resize 监听,onUnmounted 时销毁 ECharts 实例、移除监听,防止内存泄漏;
    • resize 适配:监听窗口尺寸变化,调用 chartInstance.resize() 自动调整图表大小。
  2. 父组件核心逻辑

    • 定义响应式数据(标题、宽高、饼图数据),传入子组件;
    • 提供按钮模拟数据/尺寸/标题变化,验证子组件的响应式更新能力。

四、使用注意事项

  1. 数据格式:父组件传入的 chartData 必须是 [{ name: 'xxx', value: xxx }, ...] 格式,子组件已做基础校验;
  2. 内存泄漏:子组件在 onUnmounted 中销毁 ECharts 实例、移除 resize 监听,避免页面卸载后残留事件;
  3. 自适应优化:如果需要监听父容器尺寸变化(而非窗口),可结合 element-resize-detector 库实现;
  4. 样式适配:子组件容器的宽高使用 px 单位,若需百分比,可修改 props 类型为 String(如 width: '100%')。

五、封装总结

  1. 子组件封装了 ECharts 饼图的核心逻辑,通过 props 接收父组件配置,具备数据响应式更新、窗口 resize 自适应能力;
  2. 父组件可灵活传入自定义数据,通过修改响应式数据即可触发子组件更新,使用简单;
  3. 关键优化点:销毁 ECharts 实例、移除事件监听,避免内存泄漏;深度监听数据变化,保证图表实时更新。

到此这篇关于vue3+vite+JS使用Echarts封装一个饼图(父子组件联动)的文章就介绍到这了,更多相关vue3+vite+JS用Echarts封装饼图内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue中关于computed计算属性的妙用

    Vue中关于computed计算属性的妙用

    这篇文章主要介绍了Vue中关于computed计算属性的妙用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • vue2组件进阶与插槽详解(推荐!)

    vue2组件进阶与插槽详解(推荐!)

    插槽(slot)作用是让父组件可以往子组件指定位置插入 html 结构,也是组件的一种通信方式,下面这篇文章主要给大家介绍了关于vue2组件进阶与插槽的相关资料,需要的朋友可以参考下
    2023-02-02
  • Vue3+TS+Vite+NaiveUI搭建一个项目骨架实现

    Vue3+TS+Vite+NaiveUI搭建一个项目骨架实现

    本文主要介绍了Vue3+TS+Vite+NaiveUI搭建一个项目骨架实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • 解决打包后出现错误y.a.addRoute is not a function的问题

    解决打包后出现错误y.a.addRoute is not a function的

    这篇文章主要介绍了解决打包后出现y.a.addRoute is not a function的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • 详解uniapp如何解决H5页面双标题

    详解uniapp如何解决H5页面双标题

    Uniapp打包到线上,会出现双标题问题,原因是:通过地址链接访问时,会有个浏览器自身的标题,和uniapp自身的导航栏标题重复,本文给大家介绍了uniapp如何解决H5页面双标题,需要的朋友可以参考下
    2024-10-10
  • vue实现列表拖拽排序的示例代码

    vue实现列表拖拽排序的示例代码

    本文主要介绍了vue实现列表拖拽排序的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • vue3关于时间显示格式化的问题

    vue3关于时间显示格式化的问题

    这篇文章主要介绍了vue3关于时间显示格式化的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • vue+element tree懒加载更新数据的示例代码

    vue+element tree懒加载更新数据的示例代码

    这篇文章主要介绍了vue+element tree懒加载更新数据,文中给大家补充介绍了Vue Element Ui 树形表懒加载新增、修改、删除等操作后局部数据更新的详细代码,感兴趣的朋友跟随小编一起看看吧
    2022-09-09
  • vue插件--仿微信小程序showModel实现模态提示窗功能

    vue插件--仿微信小程序showModel实现模态提示窗功能

    这篇文章主要介绍了vue插件--仿微信小程序showModel实现模态提示窗,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • 如何使用electron将vue项目打包成.exe文件(保姆级教程)

    如何使用electron将vue项目打包成.exe文件(保姆级教程)

    本文给大家介绍如何使用electron将vue项目打包成.exe文件,大家要注意一下vue2项目,使用的vue-element-admin框架,用electron打包成.exe文件,本文结合实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2024-03-03

最新评论