本文要在vue3viteJS项目中使用Echarts封装一个饼图子组件父组件中引入子组件并传入数据。传入的数据包括标题、高度、宽度、饼图数据resize监听尺寸。子组件监听饼图数据的变化来更新子组件的显示内容。文章目录一、实现思路二、完整代码实现1. 安装 ECharts 依赖2. 饼图子组件PieChart.vue3. 父组件ParentPage.vue三、关键代码解释四、使用注意事项五、封装总结一、实现思路子组件封装基于 ECharts 封装饼图组件接收父组件传入的标题、宽高、饼图数据等 props响应式处理监听饼图数据变化自动更新图表监听窗口 resize 事件自适应调整图表尺寸父组件使用导入子组件传入自定义数据实现灵活配置。二、完整代码实现1. 安装 ECharts 依赖npminstallecharts--save# 或 yarn add echarts2. 饼图子组件PieChart.vuetemplate !-- 图表容器宽高由父组件传入 -- div refchartRef classpie-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} br/{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; } /style3. 父组件ParentPage.vuetemplate div classparent-page h2饼图组件使用示例/h2 !-- 操作区修改数据/尺寸 -- div classcontrol-panel button clickchangeChartData切换饼图数据/button button clickchangeChartSize修改图表尺寸/button button clickchangeChartTitle修改图表标题/button /div !-- 引入饼图子组件传入配置 -- PieChart :titlechartTitle :widthchartWidth :heightchartHeight :chart-datachartData / /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三、关键代码解释子组件核心逻辑props 定义明确接收标题、宽高、饼图数据且对chartData做格式校验确保数据合法性图表初始化initChart方法创建 ECharts 实例并配置基础样式updateChart方法仅更新数据/标题避免重复初始化响应式监听通过watch深度监听 props 变化宽高变化时重新初始化图表数据/标题变化时仅更新配置生命周期管理onMounted时初始化图表并添加 resize 监听onUnmounted时销毁 ECharts 实例、移除监听防止内存泄漏resize 适配监听窗口尺寸变化调用chartInstance.resize()自动调整图表大小。父组件核心逻辑定义响应式数据标题、宽高、饼图数据传入子组件提供按钮模拟数据/尺寸/标题变化验证子组件的响应式更新能力。四、使用注意事项数据格式父组件传入的chartData必须是[{ name: xxx, value: xxx }, ...]格式子组件已做基础校验内存泄漏子组件在onUnmounted中销毁 ECharts 实例、移除 resize 监听避免页面卸载后残留事件自适应优化如果需要监听父容器尺寸变化而非窗口可结合element-resize-detector库实现样式适配子组件容器的宽高使用px单位若需百分比可修改 props 类型为 String如width: 100%。五、封装总结子组件封装了 ECharts 饼图的核心逻辑通过 props 接收父组件配置具备数据响应式更新、窗口 resize 自适应能力父组件可灵活传入自定义数据通过修改响应式数据即可触发子组件更新使用简单关键优化点销毁 ECharts 实例、移除事件监听避免内存泄漏深度监听数据变化保证图表实时更新。