Vue实战篇二十六:创建动态仪表盘

系列文章目录

Vue基础篇一:编写第一个Vue程序
Vue基础篇二:Vue组件的核心概念
Vue基础篇三:Vue的计算属性与侦听器
Vue基础篇四:Vue的生命周期(秒杀案例实战)
Vue基础篇五:Vue的指令
Vue基础篇六:Vue使用JSX进行动态渲染
Vue提高篇一:使用Vuex进行状态管理
Vue提高篇二:使用vue-router实现静态路由
Vue提高篇三:使用vue-router实现动态路由
Vue提高篇四:使用Element UI组件库
Vue提高篇五:使用Jest进行单元测试
Vue提高篇六: 使用Vetur+ESLint+Prettier插件提升开发效率
Vue实战篇一: 使用Vue搭建注册登录界面
Vue实战篇二: 实现邮件验证码发送
Vue实战篇三:实现用户注册
Vue实战篇四:创建多步骤表单
Vue实战篇五:实现文件上传
Vue实战篇六:表格渲染动态数据
Vue实战篇七:表单校验
Vue实战篇八:实现弹出对话框进行交互
Vue实战篇九:使用省市区级联选择插件
Vue实战篇十:响应式布局
Vue实战篇十一:父组件获取子组件数据的常规方法
Vue实战篇十二:多项选择器的实际运用
Vue实战篇十三:实战分页组件
Vue实战篇十四:前端excel组件实现数据导入
Vue实战篇十五:表格数据多选在实际项目中的技巧
Vue实战篇十六:导航菜单
Vue实战篇十七:用树型组件实现一个知识目录
Vue实战篇十八:搭建一个知识库框架
Vue实战篇十九:使用printjs打印表单
Vue实战篇二十:自定义表格合计
Vue实战篇二十一:实战Prop的双向绑定
Vue实战篇二十二:生成二维码
Vue实战篇二十三:卡片风格与列表风格的切换
Vue实战篇二十四:分页显示
Vue实战篇二十五:使用ECharts绘制疫情折线图


一、背景

  • 上一期的实战,我们借助ECharts开源可视化图表库实现一个疫情折线图。
  • 本期我们将引入计数器,结合上期实现的折线图,创建一个动态仪表盘。

在这里插入图片描述

二、滚动计数器

  • 我们将引入vue-count-to插件,实现数字滚动的效果。

在这里插入图片描述

  • vue-count-to的安装
> npm install vue-count-to
  • vue-count-to的常规用法
<template>
  <countTo :startVal='startVal' :endVal='endVal' :duration='3000'></countTo>
</template>
 
<script>
  import countTo from 'vue-count-to';
  export default {
    
    
    components: {
    
     countTo },
    data () {
    
    
      return {
    
    
        startVal: 0,
        endVal: 11149
      }
    }
  }
</script>
属性 说明
startVal 起始值
endVal 终止值
duration 动画持续时间,以毫秒为单位

三、前端实现

  • 1、我们先编写一个通用的计数器组件;
  • 2、然后在首页上加上三个自定义计数器;
  • 3、通过点击自定义计数器,动态刷新疫情折线图

3.1 编写计数器组件

  • 参照官方的例子,就可以很容易地创建出计数器组件了,这里我们的组件很简单,显示一个标题和一个数值。
  • 另外,我们在计数器面板上加入了点击事件,当鼠标点击面板时,计数器将标题返回给父组件,便于父组件来区分鼠标点击的是哪一个计数器。
  • MyCountTo.vue
<template>
  <div class="count-to-panel" @click="countToClick(countTitle)">
    <div class="count-to-content">
      <div class="count-to-title">
        {
   
   { countTitle }}
      </div>
      <count-to
        :start-val="startVal"
        :end-val="endVal"
        :duration="duration"
        class="count-to-num"
      />
    </div>
  </div>
</template>

<script>
import CountTo from 'vue-count-to'

export default {
      
      
  name: 'MyCountTo',
  components: {
      
       CountTo },
  props: {
      
      
    startVal: {
      
      
      type: Number,
      default: 0
    },
    endVal: {
      
      
      type: Number,
      default: 0
    },
    duration: {
      
      
      type: Number,
      default: 3000
    },
    countTitle: {
      
      
      type: String,
      default: '计数'
    }
  },
  methods: {
      
      
    countToClick(countTitle) {
      
      
      this.$emit('click', countTitle)
    }
  }
}
</script>

<style lang="scss" scoped>
.count-to-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, 0.05);
  border-color: rgba(0, 0, 0, 0.05);

  .count-to-content {
      
      
    font-weight: bold;
    margin: 26px;
    margin-left: 0px;
    text-align: center;

    .count-to-title {
      
      
      line-height: 18px;
      color: rgba(0, 0, 0, 0.45);
      font-size: 16px;
      margin-bottom: 12px;
    }

    .count-to-num {
      
      
      font-size: 20px;
    }
  }
}
</style>

3.2 在首页中加入三个计数器组件

  • 我们在首页加上三个计数器:江苏疫情数据,浙江疫情数据和上海疫情数据
  • dashboard/index.vue
<template>
  <div class="dashboard-container">
	<!-- 响应式布局,让三个计数器一字排开 -->
    <el-row :gutter="36">
      <el-col :xs="12" :sm="8" :lg="8">
        <my-count-to :start-val="0" :end-val="101" :duration="3000" :count-title="'江苏'" @click="setLineChartData" />
      </el-col>
      <el-col :xs="12" :sm="8" :lg="8">
        <my-count-to :start-val="0" :end-val="43" :duration="3000" :count-title="'浙江'" @click="setLineChartData" />
      </el-col>
      <el-col :xs="12" :sm="8" :lg="8">
        <my-count-to :start-val="0" :end-val="11149" :duration="3000" :count-title="'上海'" @click="setLineChartData" />
      </el-col>
    </el-row>
    
    <my-line-chart v-if="option!=null" :option="option" />

  </div>
</template>

<script>
import MyLineChart from '@/components/Echarts/MyLineChart'
import MyCountTo from './MyCountTo.vue'

export default {
      
      
  name: 'Dashboard',
  components: {
      
       MyLineChart, MyCountTo },
  data() {
      
      
    return {
      
      
      option: null,
  
    }
  },

 ...
}
</script>

<style lang="scss" scoped>
.dashboard {
      
      
  &-container {
      
      
    margin: 30px;
  }
  &-text {
      
      
    font-size: 30px;
    line-height: 46px;
  }
}
</style>
  • 让我们看下效果
    在这里插入图片描述

3.3 计数器与折线图联动

  • 接下来我们要实现计数器与疫情折线图的联动:
    – 疫情折线图的实现请参考上篇文章Vue实战篇二十五:使用ECharts绘制疫情折线图
    – 我们先在前端mock三个地区的疫情数据,然后再加入一个判断函数,该函数判断用户鼠标点击了哪个地区的计数器,就把对应的疫情数据赋值给折线图组件
  • 以下是完整源码
<template>
  <div class="dashboard-container">
     <!-- 响应式布局,让三个计数器一字排开 -->
    <el-row :gutter="36">
      <el-col :xs="12" :sm="8" :lg="8">
        <my-count-to :start-val="0" :end-val="101" :duration="3000" :count-title="'江苏'" @click="setLineChartData" />
      </el-col>
      <el-col :xs="12" :sm="8" :lg="8">
        <my-count-to :start-val="0" :end-val="43" :duration="3000" :count-title="'浙江'" @click="setLineChartData" />
      </el-col>
      <el-col :xs="12" :sm="8" :lg="8">
        <my-count-to :start-val="0" :end-val="11149" :duration="3000" :count-title="'上海'" @click="setLineChartData" />
      </el-col>
    </el-row>
    <my-line-chart v-if="option!=null" :option="option" />

  </div>
</template>

<script>
import MyLineChart from '@/components/Echarts/MyLineChart'
import MyCountTo from './MyCountTo.vue'

export default {
      
      
  name: 'Dashboard',
  components: {
      
       MyLineChart, MyCountTo },
  data() {
      
      
    return {
      
      
      option: null,
      // mock三个地区的疫情数据
      lineChartOption1: {
      
      
        xAxis: {
      
      
          name: '日期',
          data: ['4/1', '4/2', '4/3', '4/4', '4/5', '4/6', '4/7', '4/8', '4/9', '4/10', '4/11', '4/12', '4/13', '4/14', '4/15', '4/16'],
          boundaryGap: false,
          axisTick: {
      
      
            show: false
          }
        },

        tooltip: {
      
      
          trigger: 'axis',
          axisPointer: {
      
      
            type: 'cross'
          },
          padding: [5, 10]
        },
        yAxis: {
      
      
          name: '人数',
          axisTick: {
      
      
            show: false
          }
        },
        legend: {
      
      
          data: ['新增本土']
        },
        series: [{
      
      
          name: '新增本土', itemStyle: {
      
      
            normal: {
      
      
              color: '#FF005A',
              lineStyle: {
      
      
                color: '#FF005A',
                width: 2
              }
            }
          },
          smooth: true,
          type: 'line',
          data: [12, 5, 10, 7, 3, 3, 13, 5, 7, 14, 4, 3, 2, 4, 2, 7],
          animationDuration: 2800,
          animationEasing: 'cubicInOut'
        }]
      },
      lineChartOption2: {
      
      
        xAxis: {
      
      
          name: '日期',
          data: ['4/20', '4/21', '4/22', '4/23'],
          boundaryGap: false,
          axisTick: {
      
      
            show: false
          }
        },

        tooltip: {
      
      
          trigger: 'axis',
          axisPointer: {
      
      
            type: 'cross'
          },
          padding: [5, 10]
        },
        yAxis: {
      
      
          name: '人数',
          axisTick: {
      
      
            show: false
          }
        },
        legend: {
      
      
          data: ['新增本土']
        },
        series: [{
      
      
          name: '新增本土', itemStyle: {
      
      
            normal: {
      
      
              color: '#00FF60',
              lineStyle: {
      
      
                color: '#00FF60',
                width: 2
              }
            }
          },
          smooth: true,
          type: 'line',
          data: [6, 15, 10, 12],
          animationDuration: 2800,
          animationEasing: 'cubicInOut'
        }]
      },
      lineChartOption3: {
      
      
        xAxis: {
      
      
          name: '日期',
          data: ['4/26', '4/27', '4/28', '4/29', '4/30', '5/01'],
          boundaryGap: false,
          axisTick: {
      
      
            show: false
          }
        },

        tooltip: {
      
      
          trigger: 'axis',
          axisPointer: {
      
      
            type: 'cross'
          },
          padding: [5, 10]
        },
        yAxis: {
      
      
          name: '人数',
          axisTick: {
      
      
            show: false
          }
        },
        legend: {
      
      
          data: ['新增本土']
        },
        series: [{
      
      
          name: '新增本土', itemStyle: {
      
      
            normal: {
      
      
              color: '#000000',
              lineStyle: {
      
      
                color: '#000000',
                width: 2
              }
            }
          },
          smooth: true,
          type: 'line',
          data: [1606, 1292, 5487, 1249, 788, 727],
          animationDuration: 2800,
          animationEasing: 'cubicInOut'
        }]
      }
    }
  },

  methods: {
      
      
    // 根据用户鼠标点击的计数器的标题进行判断,并将对应地区的数据赋值给折线图组件
    setLineChartData(countTitle) {
      
      
      switch (countTitle) {
      
      
        case '江苏':
          this.option = this.lineChartOption1
          break
        case '浙江':
          this.option = this.lineChartOption2
          break
        case '上海':
          this.option = this.lineChartOption3
          break
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.dashboard {
      
      
  &-container {
      
      
    margin: 30px;
  }
  &-text {
      
      
    font-size: 30px;
    line-height: 46px;
  }
}
</style>


四、最终实现效果演示

在这里插入图片描述

五、源码

猜你喜欢

转载自blog.csdn.net/jpgzhu/article/details/124542859