主题
完成首页中间柱状图与左侧排名(Day12 1/2)
本页对应 day12(1),共 5 段视频,约 1 小时 40 分。
学习目标
- 能够使用 ECharts 完成首页中间柱状图配置,设置高度、标题、坐标轴、系列、提示框和指示器,并根据“销售额/访问量”动态切换标题与数据。
- 能够实现左侧排名列表布局,使用
v-for和v-if渲染销售额排名与访问量排名,并对前 3 名应用独立样式。 - 能够基于 ECharts 官方示例完成雷达图配置,设置容器高度,并调整标题、图例、雷达指标和系列数据。
- 能够完成饼图配置,设置图例、标签引导线、中心主副标题、高亮效果,并通过鼠标移入事件动态更新中心展示数据。
- 能够根据“品类/商品”切换饼图数据源,并说明 ECharts 图表实例方法在更新配置项中的应用。
- 能够说明微信小程序的基本概念、创始人张小龙、无需下载安装即用、用完即走、项目体积限制及常见小程序平台。
知识点
柱状图先解决“有没有高度”
为什么需要:ECharts 图表必须有明确高度,否则配置项写得再全也可能不显示。转写稿里反复强调“没高度”是数据可视化最常见的坑。怎么想:先审查元素,确认 v-chart 或父盒子是否被撑开;再决定给图表本身加类名/行内样式,还是给父盒子定高。怎么做:在首页中间卡片左侧放 v-chart :option="option",先给 height: 400px(调试时可改 300px),也可让父盒子有高度后让图表继承。易错点:只看代码不看元素;左侧 left、底部 bottom 不要归零,否则 Y 轴刻度、X 轴文字会看不见;右侧没有双坐标时可 right: 0。转写稿未给完整代码,以下只保留出现过的配置项名称:
js
// 仅按转写稿整理关键配置项,不补全未出现的值
v-chart :option="option"
height: 400px
title: { text, left: 'center', textStyle: { color } }
xAxis: { type: 'category', data, axisPointer: { type: 'shadow' } }
yAxis: { axisLine: { show: true }, axisTick: { show: true } }
series: [{ type: 'bar', data, itemStyle: { color }, label: { show: true } }]
tooltip: { axisPointer: { type: 'shadow' } }标题、坐标轴和 12 个月数据
为什么需要:柱状图要表达“1—12 月销售额/访问量”,必须有标题、分类轴、数值轴和系列数据。怎么想:先搭最小可显示结构,再调布局。怎么做:title.text 先写“销售额”,xAxis.type 用类目轴,series.type: 'bar' 放 12 条数据;布局用 left: 30、bottom: 30、right: 0 留出刻度空间。易错点:标题居中不是靠猜,用 left: 'center';轴线和刻度要分别用 axisLine.show、axisTick.show 打开;X 轴默认显示 0—11 索引,需要把月份数组绑定到 xAxis.data。
tooltip、指示器和柱条样式
为什么需要:鼠标移入要看到提示,柱条颜色和数值标签也要符合设计。怎么想:先查 ECharts 官网实例,找相近效果直接 CV 再调。怎么做:tooltip 配提示框,axisPointer.type: 'shadow' 做阴影指示器;itemStyle.color 调柱条颜色(可用渐变);label.show: true 让数值显示。易错点:axisPointer 放 tooltip 还是 xAxis 要按官网示例确认;找不到效果时不要盲改,先看实例里触发时机和配置位置。
标题与数据随“销售额/访问量”切换
为什么需要:同一个图表要复用于两个指标。怎么想:父组件已通过 activeName 收集当前选项,标题可用三元判断,数据从父组件传入的两组数组中二选一。怎么做:模板中判断 activeName === 'sales' 显示“销售额”,否则“访问量”;props 接收父组件 data,用 v-if/v-else 或计算属性切换 series.data。易错点:模板里会自动解包,JS 区域要 .value;v-if 与 v-for 不要随意放同一元素,V3 中 v-if 优先级更高。
左侧排名:静态结构、flex 与前三名样式
为什么需要:右侧排名不是图表,用 ul/li 更直接。怎么想:每个 li 分名次、名称、数值三部分,用 flex 做一左一右;前 3 名加特殊类。怎么做:v-for 渲染数组,index < 3 时加类名;主轴用 justify-content: space-between,名次小球用固定宽高、border-radius: 50%、文字居中;两组数据按 activeName 二选一。易错点:key 要稳定;前 3 名样式不要写成所有项;v-if/v-else 切换数组时注意数据字段名不同。
雷达图、饼图:先找官网示例再调
为什么需要:工作里图表配置项很多,不必从零手写。怎么想:先搜 ECharts 官网实例,有相似效果就复制,再换真实数据。怎么做:雷达图给高度,调 legend、数据;饼图用 radio 收集“品类/商品”,数据二选一,label 做视觉引导线,中间文字可用 title 主副标题调 left/top;鼠标移入可用 mouseover 拿到 params,通过 setOption 改标题。易错点:饼图 label 默认在中间,要移到外侧;legend 方向和位置可调;事件参数是 params,不是随便命名。
小程序简介
为什么需要:后续进入移动端和小程序。怎么想:微信小程序由张小龙/腾讯推出,特点是无需安装、用完即走,但实际仍需下载小体积包。怎么做:记住上线体积限制不超过 2MB;后续用真机测试。易错点:不是“完全不用下载”;市场上有百度、支付宝、钉钉等小程序,但本节学的是微信小程序。
本节笔记未附图片,以下保留转写稿中的关键代码。本节完成首页排名列表(笔记标题为“左侧排名”):销售额/访问量切换时,标题和列表数据同步变化。
需求与数据来源
为什么需要:首页数据可视化不能只有柱状图,还要让用户快速看到门店销售额或访问量的排名,所以排名列表要跟着顶部指标切换。
怎么想:排名列表不画图表,本质是“标题 + 列表”。标题由当前选中指标决定;列表数据由父组件提供,销售额和访问量各一个数组,二者取其一。
怎么做:父组件把首页数据通过 props 传给排名组件,模板中可直接访问 data;列表用 ul > li,每个 li 放三部分:名次、门店名、数值。
易错点:转写稿调试时特别提醒,模板里会自动解包 ref,写 activeName 即可;在 script 里才写 activeName.value。另外访问量数组没有 id 时,转写稿用索引作 key,有唯一 id 时应优先用 id。
标题随指标切换
为什么需要:用户选“销售额”时标题应是“门店销售额排名”,选“访问量”时变成“门店访问量排名”,否则标题和数据对不上。
怎么想:用三元表达式判断当前指标,activeName === 'sale' 时显示销售额排名,否则显示访问量排名。
怎么做:
html
<h1>{{ activeName === 'sale' ? '门店销售额排名' : '门店访问量排名' }}</h1>易错点:转写稿里标题一开始受全局 h1
先搭底部卡片:雷达图放在哪里
为什么需要:首页底部要放两个卡片,左侧卡片头部有“关键字搜索”和下拉菜单,下面才是雷达图。先把容器和头部搭好,图表才有稳定父级和高度。
怎么想:转写稿里先处理布局:左右两个 el-col,里面放 el-card;卡片头部不能用默认标题,而要用具名插槽 header 自定义,因为默认头部有贯穿分割线,而设计稿头部是自定义内容。
怎么做:卡片内用 header 插槽,左侧写“关键字搜索”,右侧放下拉菜单 el-dropdown;外层用 flex 的 space-between 让左右分开。下拉菜单可先用“北京、上海”等静态项占位。下拉箭头图标可保留,也可按转写稿用深度选择器调样式。
易错点:① 忘记用 header 插槽,头部结构不对;② 下拉菜单默认是点击触发,不是鼠标移入;③ 改第三方组件样式要用深度选择器;④ 父容器没高度时,后面图表不显示。
雷达图先找官方实例,不要从零硬写
为什么需要:转写稿反复强调:工作里写图表不是一个个配置项硬背,而是先看 ECharts 官网实例,有类似效果就复制过来再调。雷达图就是典型。
怎么想:先明确需求是“多维指标对比”,所以选雷达图;到 ECharts 官网搜“雷达图”,找最接近的实例,把配置项整体拿过来,再替换标题、图例、指标名和数据。
怎么做:容器写 v-chart :option="getRadar",并给高度,例如 height: 300px。配置项里保留 title、legend、radar.indicator、series。标题先改成“王者荣耀”;图例改成“男生、女生”这类两项;指标名改成“生存、发育、猥琐别浪、坚持”等;系列 type 为 radar,数据用两个数组占位。刷新后能看到雷达图,再按接口数据替换。
易错点:① 没给高度,图表不出来,先审查元素看容器高度;② 配置项记不住就查官网实例,不要懵;③ legend 的名字要和 series.data 对应;④ 指标名、最大值、文字颜色都可调,但不要一次改太多,改一项刷新验证一项。
调图例和指标:位置、方向、文字
为什么需要:官网实例只是起点,设计稿的图例位置、方向、指标文字都不一样,必须会调。
怎么想:图例由 legend 控制,位置可调 right: 0 等,方向可调 orient: 'vertical';指标文字在 radar.indicator 里改 name,最大值也可设;文字颜色可在对应样式里调。
怎么做:先把 legend.right 设为 0,看是否贴边;再把 orient 改成 vertical,看是否竖排;然后改 indicator 的 name,如“生存、发育、猥琐别浪、坚持”;刷新验证。转写稿里还提到图例方向有水平/竖着两种,调完就能看到变化。
易错点:① 把 legend 和 radar 配错位置;② 改了 name 但数据没对应;③ 图例贴边后遮挡图形,要结合容器宽度调;④ 不要忘记 series 里 type: 'radar'。
调试顺序与同页图表思路
为什么需要:转写稿的调试过程是“先复制实例→补高度→改标题→改图例→改指标→刷新看效果”。这个顺序能快速定位问题。
怎么想:先保证“能显示”,再保证“像设计稿”,最后替换真实数据。同页还有 K 线图、饼图,思路一样:官网找实例、复制配置项、调样式、换数据。
怎么做:雷达图完成后,检查容器高度、标题、图例、指标、数据五项;接口有数据时替换 series.data 和 indicator 对应值。转写稿提到“K线图直接带走配置项”“饼图也是官网实例基础上调”,说明不要重复造轮子。
易错点:① 只复制不调,图例和指标对不上;② 忘记真实数据格式可能与示例不同;③ 图表容器高度被父级压掉;④ 第三方组件样式改不动时,先查选择器层级,再用深度选择器。
课堂画面





代码示例
示例一:首页中间柱状图(ECharts,销售额 / 访问量切换)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>首页中间柱状图</title>
<style>
.card { width: 800px; margin: 20px auto; }
.tabs { display: flex; gap: 10px; margin-bottom: 10px; }
.tabs button { padding: 4px 12px; cursor: pointer; }
.tabs button.active { background: #409eff; color: #fff; border-color: #409eff; }
/* 易错点:图表容器必须给高度,否则 ECharts 画不出来 */
#barChart { width: 100%; height: 300px; }
</style>
</head>
<body>
<div class="card">
<div class="tabs">
<button data-type="fail" class="active">销售额</button>
<button data-type="visit">访问量</button>
</div>
<div id="barChart"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<script>
// 模拟父组件传过来的首页数据
const chartData = {
orderForYear: [120, 200, 150, 80, 70, 110, 130, 100, 90, 160, 140, 180], // 销售额
userForYear: [60, 80, 70, 40, 35, 55, 65, 50, 45, 80, 70, 90], // 访问量
data: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月']
};
// 相当于 Vue 里 v-model 收集到的 activeName
let activeName = 'fail';
const barChart = echarts.init(document.getElementById('barChart'));
function getOption() {
return {
// 标题:销售额 / 访问量 三元判断,颜色和位置都要调
title: {
text: activeName === 'fail' ? '销售额' : '访问量',
left: 'center',
textStyle: { color: 'yellowgreen' }
},
// 提示框:触发时机 axis,指示器类型 shadow
tooltip: {
trigger: 'axis'
},
// 布局:left / bottom 千万别归零,否则轴线刻度看不见;right 可以归零
grid: { left: 30, bottom: 30, right: 0, top: 50 },
xAxis: {
type: 'category',
data: chartData.data, // 1月 ~ 12月,替换默认的 0~11 索引
axisTick: { alignWithLabel: true },
axisPointer: { type: 'shadow' } // 阴影指示器其实在 X 轴上
},
yAxis: {
type: 'value',
axisLine: { show: true }, // 左侧轴线
axisTick: { show: true } // 左侧刻度
},
series: [{
name: activeName === 'fail' ? '销售额' : '访问量',
type: 'bar',
// 数据二选一,和标题的判断套路一模一样
data: activeName === 'fail' ? chartData.orderForYear : chartData.userForYear,
itemStyle: {
// 柱条颜色:渐变
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#83bff6' },
{ offset: 0.5, color: '#188df0' },
{ offset: 1, color: '#188df0' }
])
},
label: { show: true, position: 'inside' } // 文本标签默认就在中间
}]
};
}
barChart.setOption(getOption());
// 切换销售额 / 访问量
document.querySelectorAll('.tabs button').forEach(btn => {
btn.onclick = () => {
document.querySelectorAll('.tabs button').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
activeName = btn.dataset.type;
barChart.setOption(getOption(), true);
};
});
window.addEventListener('resize', () => barChart.resize());
</script>
</body>
</html>关键行与易错点
#barChart { height: 300px }:写数据可视化最要命的问题就是没有高度,图出不来先审查元素看高度,不要瞎改配置项。grid: { left: 30, bottom: 30, right: 0 }:left、bottom归零会导致左侧刻度和 X 轴文字消失;右侧没有坐标轴,可以归零。yAxis.axisLine.show / axisTick.show:左侧轴线和刻度默认不显示,必须手动打开。title.left: 'center'+textStyle.color:标题居中与颜色是两个位置,别只改一个。tooltip.axisPointer不生效时,指示器其实挂在 xAxis.axisPointer 上,type: 'shadow'。- 标题和
series.data都用activeName === 'fail' ? ... : ...同一个三元判断,二者必须保持一致,否则标题写“销售额”数据却是访问量。
示例二:左侧门店排名列表(flex 一左一右 + 前三名高亮)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>左侧排名</title>
<style>
.rank-card { width: 360px; margin: 20px auto; }
.rank-card h1 { font-size: 16px; }
.rank-list { list-style: none; padding: 0; margin: 0; }
.rank-list li {
display: flex; /* 主轴:一左一右 */
justify-content: space-between; /* 两端对齐,中间留剩余空间 */
align-items: center; /* 侧轴:垂直居中 */
margin: 10px 0; /* 每个 li 上下留点距离 */
font-size: 14px;
}
.rank-list li .icon {
display: inline-block;
width: 15px;
height: 15px;
line-height: 15px;
text-align: center;
font-size: 12px;
}
/* 前三个:黑底白字 + 圆形(对应模板里 index < 3 动态加类名) */
.rank-list li:nth-child(-n+3) .icon {
background: #000;
color: #fff;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="rank-card">
<h1>门店销售额排名</h1>
<ul class="rank-list">
<li><span class="icon">1</span><span class="name">华为</span><span class="num">211</span></li>
<li><span class="icon">2</span><span class="name">小米</span><span class="num">199</span></li>
<li><span class="icon">3</span><span class="name">vivo</span><span class="num">160</span></li>
<li><span class="icon">4</span><span class="name">OPPO</span><span class="num">120</span></li>
<li><span class="icon">5</span><span class="name">荣耀</span><span class="num">99</span></li>
</ul>
</div>
</body>
</html>关键行与易错点
- 这块没有用到任何图表,纯
ul > li布局,一个li代表一条排名,内部三部分:名次、名字、数量。 display: flex+justify-content: space-between:一左一右,中间自动留空;侧轴用align-items: center。不要再用浮动或写死宽度。- 前三个样式不同:纯 CSS 用
li:nth-child(-n+3) .icon;在 Vue 里对应转写稿的写法是:class="{ icon: true, active: index < 3 }",即index < 3时才加高亮类。 .icon先统一display: inline-block+ 固定15px × 15px,再单独给前三个加border-radius: 50%变成小球,否则所有名次都会变成圆圈。- 标题要随 tab 变化:
activeName === 'fail' ? '门店销售额排名' : '门店访问量排名',两个数据数组也要跟着二选一。
示例三:雷达图(直接抄官网示例,再按需改配置)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>雷达图</title>
<style>
/* 易错点:没有高度雷达图同样不显示 */
#radarChart { width: 500px; height: 300px; }
</style>
</head>
<body>
<div id="radarChart"></div>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<script>
const radarChart = echarts.init(document.getElementById('radarChart'));
radarChart.setOption({
// 标题
title: { text: '王者荣耀' },
// 图例:位置 right 归零贴右边,方向 orient 改成竖着
legend: {
right: 0,
orient: 'vertical',
data: ['男生', '女生']
},
// 雷达图的“坐标轴”:indicator 决定几个维度、每个维度的文字和最大值
radar: {
indicator: [
{ name: '生存', max: 100 },
{ name: '发育', max: 100 },
{ name: '猥琐', max: 100 },
{ name: '坚持', max: 100 },
{ name: '团战', max: 100 }
]
},
series: [{
type: 'radar',
// data 是数组,每项用 value + name,name 要和 legend 对得上
data: [
{ value: [90, 80, 70, 60, 85], name: '男生' },
{ value: [70, 65, 90, 80, 50], name: '女生' }
]
}]
});
window.addEventListener('resize', () => radarChart.resize());
</script>
</body>
</html>关键行与易错点
- 这类图表不用自己从零写,先去 ECharts 官网「示例」里找雷达图,配置项直接复制过来,再换成自己的数据,这是工作里的常规做法。
#radarChart { height: 300px }:和柱状图一样,容器没高度就是一片空白,不是配置写错了。radar.indicator里的name就是图上的文字,max决定刻度最大值,改这两项就能换成自己的业务维度。legend.data和series.data里的name必须一一对应,否则图例和图形对不上;orient: 'vertical'是竖排,right: 0是贴右边。series.type: 'radar',data里每项是{ value: [...], name: '...' },value数组长度要和indicator的维度数量一致。
常见错误
- 图表区域空白:现象是
v-chart写了但页面无图;原因是图表容器或父容器没有明确高度;修法是给容器或父盒设置固定高度,并用审查元素确认实际高度。 - 改第三方组件样式不生效:现象是样式写了但组件外观不变;原因是作用域样式未穿透;修法是用深度选择器包裹目标类名,并确认类名层级。
- 切换销售额/访问量后标题或柱状数据不更新:现象是按钮变了图表没变;原因是标题和
series.data未统一按当前状态二选一;修法是统一用当前选中值判断标题和数据源。 - 排名前三样式错乱:现象是前三条和后续样式一样,或第一个圆形没生效;原因是动态类判断或
nth-child使用不对;修法是用索引<3加类,第一个单独用nth-child(1)处理。 - 饼图鼠标移入后中间数值不更新:现象是悬停高亮但标题/数值不变;原因是只写了静态标题,未监听
mouseover调setOption;修法是从事件参数取name/value,更新主标题和副标题。 - 图例或视觉引导线遮挡内容:现象是文字压图、图例位置不合适;原因是
legend、labelLine、radius、left/top未按容器调整;修法是参考官网实例调图例方向/位置、引导线和半径,预留边距。
练习
- 给首页中间柱状图容器补高度,并实现“销售额/访问量”切换时标题和
series.data同步变化。 - 完成左侧排名列表:前三条高亮,第一条排名做成圆形,并验证动态类名只加在前三项。
- 从 ECharts 官网找一个雷达图示例接入项目,调整图例位置和标题后说明改了哪些配置项。
- 实现饼图鼠标移入时中间标题显示当前项名称和值,移出后恢复到默认项。
- 列出小程序项目超过 2MB 时的 3 个排查点和对应处理方式。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 完成首页中间柱状图 | 21:55 |
| 2 | 左侧排名 | 15:11 |
| 3 | 雷达图 | 17:36 |
| 4 | 饼图 | 29:26 |
| 5 | 微信小程序简介 | 15:52 |
小结
- 图表类需求先保证容器高度,再排查配置项,审查元素应成为第一反应。
- 第三方 UI 组件样式要改,优先确认作用域和深度选择器。
- 图表数据切换应由当前选中状态统一驱动,避免标题、数据、图例各写一套。
- 复杂图表优先找官网实例改造,再按业务数据替换和微调。
- 交互态展示要结合图表事件与
setOption,不能只改静态模板。 - 排名、列表类布局要区分索引规则和第一个特殊样式,动态类名要验证。
- 小程序入门重点是组件使用和体积限制,上线前要关注资源压缩与真机效果。