【若依前后端分离】首页-多个按钮控制同一个图表

示例图:上面四个框可以点击

 

重要代码片段 :

index_v1中

<panel-group @handleSetLineChartData="handleSetLineChartData" :data="totalData"/>
  1. : 这是一个自定义的 Vue 组件。名称是 panel-group
  2. @handleSetLineChartData="handleSetLineChartData": 这是一个事件监听器。在 Vue.js 中,@ 是 v-on: 的简写,用于监听 DOM 事件。这意味着当 panel-group 组件触发一个名为 handleSetLineChartData 的事件时,它将调用当前 Vue 实例中的 handleSetLineChartData 方法。
  3. :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不生效可以留言~

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值