课程名称:Vue + EChart 4.0 从0到1打造商业级数据报表项目
课程章节:重构核心指标组件之销售组件日期组件
课程讲师: Sam
课程内容:
使用vue-echart重构,重构的样式会很简洁,无关的样式比如获取DOM等都可以删除了
创建公共的style样式
src/style/index.css
.echarts {
width: 100%;
height: 100%;
}
.el-card__header {
border-bottom: none;
padding: 0;
}
在mian.js中引入css
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './plugins/element.js'
import './plugins/vcharts'
import ECharts from 'echarts'
import VueECharts from 'vue-echarts'
import './style/index.css' // 新增
Vue.config.productionTip = false
Vue.prototype.$echarts = ECharts
Vue.component('v-chart', VueECharts)
new Vue({
router,
render: h => h(App)
}).$mount('#app')
重构累计订单TotalOrders
<template>
<common-card
title="累计订单量"
:value="orderToday"
>
<template>
<v-chart :options="getOptions()" />
</template>
<template v-slot:footer>
<span>昨日订单量 </span>
<span class="emphasis">{{orderLastDay}}</span>
</template>
</common-card>
</template>
<script>
import commonCardMixin from '../../mixins/commonCardMixin'
import commonDataMixin from '../../mixins/commonDataMixin'
export default {
mixins: [commonCardMixin, commonDataMixin],
methods: {
getOptions() {
return this.orderTrend.length > 0 ? {
xAxis: {
type: 'category',
show: false,
boundaryGap: false
},
yAxis: {
show: false
},
series: [{
type: 'line',
data: this.orderTrend,
areaStyle: {
color: 'purple'
},
lineStyle: {
width: 0
},
itemStyle: {
opacity: 0
},
smooth: true
}],
grid: {
top: 0,
bottom: 0,
left: 0,
right: 0
}
} : null
}
}
}
</script>
修改TodayUsers/index.vue
<template>
<common-card
title="今日交易用户数"
:value="orderUser"
>
<template>
<v-chart :options="getOptions()" />
</template>
<template v-slot:footer>
<span>退货率 </span>
<span class="emphasis">{{returnRate}}</span>
</template>
</common-card>
</template>
<script>
import commonCardMixin from '../../mixins/commonCardMixin'
import commonDataMixin from '../../mixins/commonDataMixin'
export default {
mixins: [commonCardMixin, commonDataMixin],
methods: {
getOptions() {
return {
color: ['#3398DB'],
tooltip: {},
series: [{
name: '用户实时交易量',
type: 'bar',
data: this.orderUserTrend,
barWidth: '60%'
}],
xAxis: {
type: 'category',
data: this.orderUserTrendAxis,
show: false
},
yAxis: {
show: false
},
grid: {
top: 0,
left: 0,
bottom: 0,
right: 0
}
}
}
}
}
</script>
<style lang="scss" scoped>
</style>
重构TotalUsers
<template>
<common-card
title="累计用户数"
:value="userToday"
>
<template>
<v-chart :options="getOptions()" />
</template>
<template v-slot:footer>
<div class="total-users-footer">
<span>日同比</span>
<span class="emphasis">{{userGrowthLastDay}}</span>
<div class="increase" />
<span class="month">月同比</span>
<span class="emphasis">{{userGrowthLastMonth}}</span>
<div class="decrease" />
</div>
</template>
</common-card>
</template>
<script>
import commonCardMixin from '../../mixins/commonCardMixin'
import commonDataMixin from '../../mixins/commonDataMixin'
export default {
mixins: [commonCardMixin, commonDataMixin],
methods: {
getOptions() {
return {
grid: {
left: 0,
right: 0,
top: 0,
bottom: 0
},
xAxis: {
type: 'value',
show: false
},
yAxis: {
type: 'category',
show: false
},
series: [{
name: '上月平台用户数',
type: 'bar',
stack: '总量',
data: [this.userLastMonth],
barWidth: 10,
itemStyle: {
color: '#45c946'
}
}, {
name: '今日平台用户数',
type: 'bar',
stack: '总量',
data: [this.userTodayNumber],
itemStyle: {
color: '#eee'
}
}, {
type: 'custom',
stack: '总量',
data: [this.userLastMonth],
renderItem: (params, api) => {
const value = api.value(0)
const endPoint = api.coord([value, 0])
return {
type: 'group',
position: endPoint,
children: [{
type: 'path',
shape: {
d: 'M1024 255.996 511.971 767.909 0 255.996 1024 255.996z',
x: -5,
y: -20,
width: 10,
height: 10,
layout: 'cover'
},
style: {
fill: '#45c946'
}
}, {
type: 'path',
shape: {
d: 'M0 767.909l512.029-511.913L1024 767.909 0 767.909z',
x: -5,
y: 10,
width: 10,
height: 10,
layout: 'cover'
},
style: {
fill: '#45c946'
}
}]
}
}
}]
}
}
}
}
</script>
<style lang="scss" scoped>
.total-users-footer {
display: flex;
align-items: center;
.month {
margin-left: 10px;
}
}
</style>
改造sales组件
<template>
<div class="sales-view">
<el-card shadow="hover" :body-style="{ padding: '0 0 20px 0' }">
<template v-slot:header>
<div class="menu-wrapper">
<el-menu
:default-active="activeIndex"
mode="horizontal"
@select="onMenuSelect"
class="sales-view-menu"
>
<el-menu-item index="1">销售额</el-menu-item>
<el-menu-item index="2">访问量</el-menu-item>
</el-menu>
<div class="menu-right">
<el-radio-group v-model="radioSelect" size="small">
<el-radio-button label="今日" />
<el-radio-button label="本周" />
<el-radio-button label="本月" />
<el-radio-button label="今年" />
</el-radio-group>
<el-date-picker
type="daterange"
v-model="date"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
size="small"
unlink-panels
:picker-options="pickerOptions"
class="sales-view-date-picker"
/>
</div>
</div>
</template>
<template>
<div class="sales-view-chart-wrapper">
<v-chart :options="chartOption" />
<div class="sales-view-list">
<div class="sales-view-title">排行榜</div>
<div class="list-item-wrapper">
<div class="list-item" v-for="item in rankData" :key="item.no">
<div :class="['list-item-no', +item.no <= 3 ? 'top-no' : '']">{{item.no}}</div>
<div class="list-item-name">{{item.name}}</div>
<div class="list-item-money">{{item.money}}</div>
</div>
</div>
</div>
</div>
</template>
</el-card>
</div>
</template>
<script>
import commonDataMixin from '../../mixins/commonDataMixin'
export default {
mixins: [commonDataMixin],
data() {
return {
activeIndex: '1',
radioSelect: '今日',
date: null,
pickerOptions: {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 24 * 1000 * 7)
picker.$emit('pick', [start, end])
}
}, {
text: '最近一个月',
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 24 * 1000 * 30)
picker.$emit('pick', [start, end])
}
}, {
text: '最近三个月',
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 24 * 1000 * 90)
picker.$emit('pick', [start, end])
}
}]
},
chartOption: {}
}
},
computed: {
rankData() {
return this.activeIndex === '1' ? this.orderRank : this.userRank
}
},
watch: {
orderFullYear() {
this.render(this.orderFullYear, this.orderFullYearAxis, '年度销售额')
}
},
methods: {
onMenuSelect(index) {
this.activeIndex = index
if (index === '1') {
this.render(this.orderFullYear, this.orderFullYearAxis, '年度销售额')
} else {
this.render(this.userFullYear, this.userFullYearAxis, '年度用户访问量')
}
},
render(data, axis, title) {
this.chartOption = {
title: {
text: title,
textStyle: {
fontSize: 12,
color: '#666'
},
left: 25,
top: 20
},
xAxis: {
type: 'category',
data: axis,
axisTick: {
alignWithLabel: true,
lineStyle: {
color: '#999'
}
},
axisLine: {
lineStyle: {
color: '#999'
}
},
axisLabel: {
color: '#333'
}
},
yAxis: {
axisLine: {
show: false
},
axisTick: {
show: false
},
splitLine: {
lineStyle: {
type: 'dotted',
color: '#eee'
}
}
},
series: [{
type: 'bar',
barWidth: '35%',
data
}],
color: ['#3398DB'],
grid: {
top: 70,
left: 60,
right: 60,
bottom: 50
}
}
}
}
}
</script>
<style lang="scss" scoped>
.sales-view {
margin-top: 20px;
.menu-wrapper {
position: relative;
display: flex;
.sales-view-menu {
width: 100%;
padding-left: 20px;
.el-menu-item {
height: 50px;
line-height: 50px;
margin: 0 20px;
}
}
.menu-right {
position: absolute;
top: 0;
right: 20px;
height: 50px;
display: flex;
align-items: center;
justify-content: flex-end;
.sales-view-date-picker {
margin-left: 20px;
}
}
}
.sales-view-chart-wrapper {
display: flex;
height: 270px;
.echarts {
flex: 0 0 70%;
width: 70%;
height: 100%;
}
.sales-view-list {
flex: 1;
width: 100%;
height: 100%;
overflow: hidden;
.sales-view-title {
margin-top: 20px;
font-size: 12px;
color: #666;
font-weight: 500;
}
.list-item-wrapper {
margin-top: 15px;
.list-item {
display: flex;
align-items: center;
font-size: 12px;
height: 20px;
padding: 6px 20px 6px 0;
.list-item-no {
display: flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
color: #333;
&.top-no {
background: #000;
border-radius: 50%;
color: #fff;
font-weight: 500;
}
}
.list-item-name {
margin-left: 10px;
color: #333;
}
.list-item-money {
flex: 1;
text-align: right;
}
}
}
}
}
}
</style>
课程收获:
学习到了如何使用vue-echarts对现在的业务进行重构,深入链接了,date-picker代码实现的原理,查看源码实现自定义参数,还可以根据自己项目需求自定义一周,一个月,一年的实现,更加贴近项目的需求,在vue-echarts中只要是自,自定义每个组件的:options,然后跟据需要展示的内容,配置固定的参数就可以实现了,vue-echarts配置细节确实需要了解透彻,然后知道如何查看源码,才可以更快的,更加有效的完成项目的需求,期待后面认真的学习ing
点击查看更多内容
1人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦