示例图:上面四个框可以点击
重要代码片段 :
index_v1中
<panel-group @handleSetLineChartData="handleSetLineChartData" :data="totalData"/>
- : 这是一个自定义的 Vue 组件。名称是
panel-group
。- @handleSetLineChartData="handleSetLineChartData": 这是一个事件监听器。在 Vue.js 中,
@
是v-on:
的简写,用于监听 DOM 事件。这意味着当panel-group
组件触发一个名为handleSetLineChartData
的事件时,它将调用当前 Vue 实例中的handleSetLineChartData
方法。- :data="totalData": 这是一个属性绑定。在 Vue.js 中,
:
是v-bind:
的简写,用于绑定一个属性到一个表达式。这里,它将panel-group
组件的data
属性绑定到当前 Vue 实例的totalData
数据属性。这意味着panel-group
组件内部可以访问并使用这个data
属性。总的来说,这段代码的意思是:渲染一个名为
panel-group
的自定义组件,当该组件触发handleSetLineChartData
事件时,调用handleSetLineChartData
方法,并将totalData
数据属性传递给该组件的data
属性。
methods: {handleSetLineChartData(type) {this.lineChartData.type=type;console.log("点击上方按钮的数据变化type:",this.lineChartData)}, }定义了一个名为
handleSetLineChartData
的方法。这个方法接受一个参数type
,并将这个type
值赋给this.lineChartData.type。
PanelGroup.vue中
<div class="card-panel" @click="handleSetLineChartData('inBound')">表示一个
div
元素,它具有一个card-panel
类,并且当这个div
被点击时,它会调用handleSetLineChartData
方法并传递'inBound'
字符串作为参数。这里是具体的分解:
<div class="card-panel">
:这是一个div
元素,它有一个card-panel
类,通常用于 CSS 样式或 JavaScript 选择器。
@click="handleSetLineChartData('inBound')"
:这是一个事件监听器,它监听click
事件。当这个div
被点击时,它会执行handleSetLineChartData
方法,并传递一个字符串参数'inBound'
。
@
是v-on:
的简写,用于监听 DOM 事件。click
是要监听的事件名称,即鼠标点击事件。"handleSetLineChartData('inBound')"
是当事件触发时要调用的方法,并传递一个参数。在这个例子中,当
div
被点击时,handleSetLineChartData
方法将被调用,并且type
参数将被设置为'inBound'
。这通常用于更新组件的状态或触发其他操作,比如更新图表数据。
//接收TotalData props: {data: {typeof: Object,//数据类型required: true//必须的} },methods: {handleSetLineChartData(type) {this.$emit('handleSetLineChartData', type)} }分析:
props
用于子组件接收父组件传递下来的数据handleSetLineChartData(type)
: 这是一个方法,它接受一个参数type
。this.$emit('handleSetLineChartData', type)
: 在这个方法中,组件使用$emit
方法触发一个自定义事件,事件的名称也是handleSetLineChartData
,并且传递了type
参数。这通常用于通知父组件某些状态的变化或者触发父组件的某个方法。现在,将这两部分结合起来解释:
当父组件使用
<panel-group />
组件,并传递一个data prop
时,这个data
会被panel-group
组件接收并使用。如果panel-group
组件内部需要通知其父组件更新线性图表的数据类型,它会调用handleSetLineChartData
方法,并传递相应的type
。通过$emit
,这个事件和参数会被发送到父组件,父组件可以监听这个事件并调用相应的处理函数(如handleSetLineChartData
),从而更新线性图表的数据。
全部代码:
index_v1.vue
<template><div class="dashboard-editor-container"><panel-group @handleSetLineChartData="handleSetLineChartData" :data="totalData"/><el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;"><line-chart :chart-data="lineChartData" v-if="!isLoading1"/></el-row><el-row :gutter="32"><el-col :xs="24" :sm="24" :lg="8"><div class="chart-wrapper"><raddar-chart/></div></el-col><el-col :xs="24" :sm="24" :lg="8"><div class="chart-wrapper"><pie-chart/></div></el-col><el-col :xs="24" :sm="24" :lg="8"><div class="chart-wrapper"><bar-chart/></div></el-col></el-row></div>
</template><script>
import PanelGroup from './dashboard/PanelGroup'
//折线图
import LineChart from './dashboard/LineChart'
//雷达图
import RaddarChart from './dashboard/RaddarChart'
//饼图
import PieChart from './dashboard/PieChart'
//柱状图
import BarChart from './dashboard/BarChart'
import BackGrand from "@/views/dashboard/BackGrand";
import {getTotalData,getStatistics} from "@/api";
const lineChartData = {//折线图type:"inBound",inBound: [],outBound: [],returnBound: [],inventory: [],dateData:[]
}
export default {name: 'Index',components: {PanelGroup,LineChart,RaddarChart,PieChart,BarChart,BackGrand},data() {return {// lineChartData: lineChartData.inBound,lineChartData:{},totalData: {},isLoading1 :true,}},created() {this.getTotalData();this.getStatistics();},methods: {handleSetLineChartData(type) {this.lineChartData.type=type;console.log("点击上方按钮的数据变化type:",this.lineChartData)//this.lineChartData = lineChartData[type]},getTotalData() {getTotalData().then(response =>{console.log("response",response);this.totalData=response.data;})},getStatistics() {getStatistics().then(response =>{console.log("response1",response);//this.lineChartData=response.data;this.lineChartData.inBound=response.data.map(item=>item.everydayInboundCount);console.log("inBound",this.lineChartData.inBound);this.lineChartData.outBound=response.data.map(item=>item.everydayOutboundCount);console.log("outbound:",this.lineChartData.outBound)this.lineChartData.returnBound=response.data.map(item=>item.everydayReturnboundCount);console.log("returnbound:",this.lineChartData.returnBound)this.lineChartData.inventory=response.data.map(item=>item.inventoryCount);console.log("inventory:",this.lineChartData.inventory)this.lineChartData.dateData=response.data.map(item=>item.date);this.isLoading1 = false;this.lineChartData.type="inBound";})},}
}
</script><style lang="scss" scoped>
.dashboard-editor-container {padding: 32px;background-color: rgb(240, 242, 245);position: relative;.chart-wrapper {background: #fff;padding: 16px 16px 0;margin-bottom: 32px;}
}@media (max-width: 1024px) {.chart-wrapper {padding: 8px;}
}#main{width:auto;height: auto;}</style>
PanelGroup.vue
<template><el-row :gutter="40" class="panel-group"><el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"><div class="card-panel" @click="handleSetLineChartData('inBound')"><div class="card-panel-icon-wrapper icon-people"><svg-icon icon-class="in" class-name="card-panel-icon" /></div><div class="card-panel-description"><div class="card-panel-text">数量一</div><count-to :start-val="0" :end-val="data.inBoundTotal" :duration="2600" class="card-panel-num" /></div></div></el-col><el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"><div class="card-panel" @click="handleSetLineChartData('outBound')"><div class="card-panel-icon-wrapper icon-message"><svg-icon icon-class="out" class-name="card-panel-icon" /></div><div class="card-panel-description"><div class="card-panel-text">数量二</div><count-to :start-val="0" :end-val="data.outBoundTotal" :duration="3000" class="card-panel-num" /></div></div></el-col><el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"><div class="card-panel" @click="handleSetLineChartData('returnBound')"><div class="card-panel-icon-wrapper icon-money"><svg-icon icon-class="returnDetail" class-name="card-panel-icon" /></div><div class="card-panel-description"><div class="card-panel-text">数量三</div><count-to :start-val="0" :end-val="data.returnBoundTotal" :duration="3200" class="card-panel-num" /></div></div></el-col><el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"><div class="card-panel" @click="handleSetLineChartData('inventory')"><div class="card-panel-icon-wrapper icon-shopping"><svg-icon icon-class="international" class-name="card-panel-icon" /></div><div class="card-panel-description"><div class="card-panel-text">数量四</div><count-to :start-val="0" :end-val="data.inventoryTotal" :duration="3600" class="card-panel-num" /></div></div></el-col></el-row>
</template><script>
import CountTo from 'vue-count-to'export default {props: {data: {typeof: Object,//数据类型required: true//必须的}},components: {CountTo},created() {console.log("数量数据:",this.data)},methods: {handleSetLineChartData(type) {this.$emit('handleSetLineChartData', type)}}
}
</script><style lang="scss" scoped>
.panel-group {margin-top: 18px;.card-panel-col {margin-bottom: 32px;}.card-panel {height: 108px;cursor: pointer;font-size: 12px;position: relative;overflow: hidden;color: #666;background: #fff;box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);border-color: rgba(0, 0, 0, .05);&:hover {.card-panel-icon-wrapper {color: #fff;}.icon-people {background: #40c9c6;}.icon-message {background: #36a3f7;}.icon-money {background: #f4516c;}.icon-shopping {background: #34bfa3}}.icon-people {color: #40c9c6;}.icon-message {color: #36a3f7;}.icon-money {color: #f4516c;}.icon-shopping {color: #34bfa3}.card-panel-icon-wrapper {float: left;margin: 14px 0 0 14px;padding: 16px;transition: all 0.38s ease-out;border-radius: 6px;}.card-panel-icon {float: left;font-size: 48px;}.card-panel-description {float: right;font-weight: bold;margin: 26px;margin-left: 0px;.card-panel-text {line-height: 18px;color: rgba(0, 0, 0, 0.45);font-size: 16px;margin-bottom: 12px;}.card-panel-num {font-size: 20px;}}}
}@media (max-width:550px) {.card-panel-description {display: none;}.card-panel-icon-wrapper {float: none !important;width: 100%;height: 100%;margin: 0 !important;.svg-icon {display: block;margin: 14px auto !important;float: none !important;}}
}
</style>
LineChart.vue
这个有点问题,不知道为什么watch检测不到数据变化,所以使用了定时器。
<template><div :class="className" :style="{height:height,width:width}"/>
</template><script>
import * as echarts from 'echarts'require('echarts/theme/macarons') // echarts theme
import resize from './mixins/resize'export default {mixins: [resize],props: {className: {type: String,default: 'chart'},width: {type: String,default: '98%'},height: {type: String,default: '350px'},autoResize: {type: Boolean,default: true},chartData: {type: Object,required: true}},data() {return {chart: null,needData: [],displayName:'出库量',timerId: null}},// watch: {// chartData: {// // deep: true,// handler(val) {// // this.setOptions(val)// this.initChart();// console.log("watch检测到数据变化,")// }// }// },
/* watch: {chartData(newValue, oldValue) {console.log('Message changed from', oldValue, 'to', newValue);}},*/mounted() {// 启动定时器this.timerId = setInterval(this.yourMethod, 500); // 每1000毫秒调用一次yourMethod方法this.$nextTick(() => {this.initChart();console.log("chartData:", this.chartData)console.log("chartData:", this.chartData.dateData)console.log("chartData:", this.chartData.inBound)this.getData();console.log("进入页面折线图展示的数据",this.needData)})},beforeDestroy() {if (!this.chart) {return}this.chart.dispose()this.chart = null// 清除定时器if (this.timerId) {clearInterval(this.timerId);}},methods: {yourMethod() {// 你的方法逻辑// console.log('定时器触发的方法',this.chartData);this.getData();this.setOptions(this.needData);},initChart() {this.chart = echarts.init(this.$el, 'macarons')this.getData();// this.setOptions(this.chartData.inBound)this.setOptions(this.needData);console.log("初始化chartData数据", this.chartData)console.log("展示数据", this.needData)},getData() {if (this.chartData.type === "inventory") {this.needData = this.chartData.inventory; this.displayName="数量一"} else if (this.chartData.type === "inBound") {this.needData = this.chartData.inBound;this.displayName="数量二"} else if (this.chartData.type === "outBound") {this.needData = this.chartData.outBound;this.displayName="数量三"} else {this.needData = this.chartData.returnBound;this.displayName="数量四"}},setOptions() {this.chart.setOption({xAxis: {// data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],//留取后五位data: this.chartData.dateData.map(date => date.substr(-5)),boundaryGap: false,//有竖线// splitLine: {// show: true,// lineStyle: {// color: "rgba(31,99,163,.5)",// },// },axisLine: {// show:false,lineStyle: {color: "rgba(31,99,163,.5)",},},axisLabel: {color: "#7EB7FD",fontWeight: "500",},axisTick: {show: false}},grid: {//布局show: true,left: 10,right: 10,bottom: 20,top: 30,containLabel: true,borderColor: "#1F63A3",},tooltip: {trigger: 'axis',axisPointer: {type: 'cross'},padding: [5, 10]},yAxis: {//有横线splitLine: {show: true,lineStyle: {color: "rgba(213,188,143,0.1)",},},axisLine: {lineStyle: {//横着指示线颜色color: "rgba(31,99,163,.5)",},},axisLabel: {color: "#7EB7FD",fontWeight: "500",},axisTick: {show: false},},legend: {data: ['11', '22']},series: [{name: this.displayName,smooth: true,type: 'line',itemStyle: {normal: {color: '#3888fa',lineStyle: {color: '#3888fa',width: 2},areaStyle: {color: '#f3f8ff'}}},data: this.needData,animationDuration: 2800,animationEasing: 'quadraticOut',//最大值点markPoint: {data: [{name: "最大值",type: "max",valueDim: "y",symbol: "rect",symbolSize: [60, 26],symbolOffset: [0, -20],itemStyle: {color: "rgba(0,0,0,0)",},label: {color: "#107efc",backgroundColor: "rgba(0,102,204,0.1)",borderRadius: 6,padding: [7, 14],borderWidth: 0.5,borderColor: "rgba(4,35,114,0.5)",formatter: this.displayName+":{c}",},},{name: "最大值",type: "max",valueDim: "y",symbol: "circle",symbolSize: 6,itemStyle: {color: "#2f5eb6",//最大点shadowColor: "#2f5eb6",shadowBlur: 8,},label: {formatter: "",},},],},}]})}}
}
</script>
记录学习日常~
有大佬晓得为什么watch不生效可以留言~