zoukankan      html  css  js  c++  java
  • 工作笔记七——vue项目中使用ref属性刷新当前子路由

    最近项目上有这样一个需求,做统计图表的展示,但是要在一个页面实现图表的切换和按日期条件的查询。

    类似这样的。点击图标选择器会弹出一个列表供用户选择要看的图表类型,图表选定后,点击右上角的选择日期会查询数据刷新当前的图表。

    其实,这种需求最简单的做法,就是将所有的图表写在一个界面中。但是每个图表的配置项不同,图表一多的话,界面代码将会非常臃肿且难以维护。所以我没有使用这种方法。我采取了子路由的方式。

    首先配置路由:

    {
          path: '/chartBox',
          name: 'chartBox',
          component: chartBox,
          children: [
            {
              name:'',
              path:'',
              component: CustomerCategory
            },
            {
              name: 'CustomerCategory',
              path: 'CustomerCategory',
              component: CustomerCategory
            },
            {
              name: 'MonthlySalesStatistics',
              path: 'MonthlySalesStatistics',
              component: MonthlySalesStatistics
            },
            {
              name: 'MonthlyTask',
              path: 'MonthlyTask',
              component: MonthlyTask
            },
            {
              name: 'OppFunnel',
              path: 'OppFunnel',
              component: OppFunnel
            },
            {
              name: 'SaleRank',
              path: 'SaleRank',
              component: SaleRank
            }
          ]
        }
    可以看到,这五张图表都在chartBox这个父路由下,这就构成了一个父子路由的关系。另外,配置一个空路由,可以让用户点击进来的时候可以看到一个默认展示的图表,如果不设置,那么进入chartBox页面将会只显示一个选择器,只有再手动选择图表才会有相应的显示。

    我们知道,当我们切换图表的时候,会调用对应图表界面的指定方法,这里的图表数据展示不会有问题。但是,当我们选定一张图表后,想要根据日期来查询其它数据,可就没这么简单了。你怎么触发数据更新呢?

    我们来看看父路由界面的编码:

    <!--
        @CreationDate:2018/3/14
        @Author:Joker
        @Usage:图表展示主界面,根据picker切换展示不同的子路由界面
    -->
    <template>
      <div class="chart-box">
    
    
        <mt-header fixed title="图表首页">
          <router-link to="/tool" slot="left">
            <mt-button icon="back">返回</mt-button>
          </router-link>
          <mt-button slot="right" @click="togglePicker">选择日期</mt-button>
        </mt-header>
    
        <div class="chart-selector">
          <span>请选择</span>
          <div class="input-box">
            <input v-model="chartTypeText" readonly/>
            <span @click="openPicker"><i class="fa fa-chevron-down" style="color: #73ccff"></i></span>
          </div>
        </div>
    
        <!--路由出口-->
        <div class="chart-container">
          <router-view ref="chartView"></router-view>
        </div>
    
        <!--图表类型Picker-->
        <mt-popup
          style="100%;"
          :closeOnClickModal="false"
          v-model="popupVisible"
          position="bottom">
          <div class="picker-toolbar">
            <span @click="cancelSelect">取消</span>
            <span @click="confirmSelect">确定</span>
          </div>
          <mt-picker :slots="slots" @change="onValuesChange" valueKey="text"></mt-picker>
        </mt-popup>
    
        <!--日期picker-->
        <mt-popup
          style=" 100%"
          :closeOnClickModal="false"
          v-model="popupDateVisible"
          position="bottom">
          <div class="picker-toolbar">
            <span @click="cancelSelectDate">取消</span>
            <span @click="confirmSelectDate">确定</span>
          </div>
          <mt-picker :slots="dateSlots" @change="onDateValuesChange" valueKey="text"></mt-picker>
        </mt-popup>
    
      </div>
    </template>
    <style scoped lang="scss">
      .chart-box {
        .chart-container {
          text-align: center;
          margin-top: 10px;
        }
        .picker-toolbar {
          height: 45px !important;
           100%;
          line-height: 45px;
          background: #f5f8fa;
          border-bottom: 0.03rem solid #eaeaea;
          font-size: 15px;
          span {
            display: inline-block;
             50%;
            text-align: center;
            color: #26a2ff;
            font-size: 15px;
            line-height: 45px;
          }
          span:first-child {
            float: left;
          }
          span:last-child {
            float: right;
          }
        }
        .chart-selector {
          background-color: white;
          margin: 50px 10px 0 10px;
          display: flex;
          line-height: 40px;
          border-radius: 10px;
          span:first-child {
            text-align: center;
            vertical-align: middle;
            padding: 0 10px;
          }
          .input-box {
            flex: 1;
            display: flex;
            font-size: 15px;
            align-items: center;
            background-color: #b8bbbf55;
            border-bottom-right-radius: 8px;
            border-top-right-radius: 8px;
            input {
              flex: 1;
              height: 40px;
              line-height: 40px;
              border: none;
              padding-left: 5px;
            }
            span {
               25px;
              text-align: center;
            }
          }
    
        }
      }
    </style>
    <script>
    
      import {Indicator} from 'mint-ui'
    
      export default {
        name: 'chartBox',
        created(){
          let _footer = this.$store.state.footerVisible;
          if (_footer) {
            this.$store.commit('TOGGLE_FOOTER');
          }
        },
        data(){
          return {
            popupDateVisible: false,
            popupVisible: false,
            slots: [{
              flex: 1,
              values: [
                {text: '每月销量统计', value: 'MonthlySalesStatistics'},
                {text: '销售排名情况', value: 'SaleRank'},
                {text: '客户分类结构', value: 'CustomerCategory'},
                {text: '商机漏斗图', value: 'OppFunnel'},
                {text: '每月任务量及完成情况', value: 'MonthlyTask'},
              ],
              textAlign: 'center'
            }],
            goChart: '',
            tmp: '',
            dateSlots: [{
              flex: 1,
              values: [],
              textAlign: 'center'
            },
              {
                divider: true,
                content: '-',
              }, {
                flex: 1,
                values: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
                textAlign: 'center'
              }],
            yearRange: [],
          }
        },
        computed: {
          'chartTypeText': function () {
            return this.$store.state.chartType;
          }
        },
        mounted(){
          for (let i = 2017; i < 2117; i++) {
            this.yearRange.push(i);
          }
          this.dateSlots[0].values = this.yearRange;
        },
        methods: {
          //表格picker
          openPicker(){
            this.popupVisible = true
          },
          cancelSelect(){
            this.popupVisible = false
          },
          confirmSelect(){
            this.$router.replace({name: this.goChart});
            this.popupVisible = false;
            this.$store.commit('setChartType', this.tmp);
          },
          onValuesChange(picker, values){
            if (values[0]) {
              this.goChart = values[0]['value'];
              this.tmp = values[0]['text']
            }
          },
          //日期Picker
          togglePicker(){
            this.popupDateVisible = true;
          },
          cancelSelectDate(){
            this.popupDateVisible = false
          },
          confirmSelectDate(){
            //刷新当前子路由界面
            if (this.goChart === 'MonthlySalesStatistics') {
              let data = {x1: [], x2: []};
              for (let i = 0; i < 12; i++) {
                data.x1.push(Math.floor(Math.random() * 100 + 1));
                data.x2.push(Math.floor(Math.random() * 100 + 1));
              }
              this.$refs.chartView.drawLine(data)
            }else if(this.goChart === 'SaleRank'){
              let data = {x: []};
              for (let i = 0; i < 7; i++) {
                data.x.push(Math.floor(Math.random() * 100 + 1));
              }
              this.$refs.chartView.drawLine(data)
            }
            this.popupDateVisible = false
          },
          onDateValuesChange(picker, values){
            let year = values[0];
            let month = values[1];
            if (year && month) {
              let d = new Date(year + '-' + month);
              console.info(d)
            }
          }
        }
      }
    </script>
    
    上面的代码,最核心的,是配置路由出口的时候,给了一个ref的属性:

    <router-view ref="chartView"></router-view>
    ref属性呢,可以帮助我们拿到当前使用组件,也就是说,ref代表了当前展示的子路由对应的组件。我们可以使用this.$refs.chartView 来调用对应组件的方法。为了节省代码量,我给每一个图表界面都提供了一个drawLine的方法用于渲染展示图表,这样,在我们选择日期的时候,点击确认,就可以刷新当前路由了。

    confirmSelectDate(){
            //刷新当前子路由界面
            if (this.goChart === 'MonthlySalesStatistics') {
              let data = {x1: [], x2: []};
              for (let i = 0; i < 12; i++) {
                data.x1.push(Math.floor(Math.random() * 100 + 1));
                data.x2.push(Math.floor(Math.random() * 100 + 1));
              }
              this.$refs.chartView.drawLine(data)
            }else if(this.goChart === 'SaleRank'){
              let data = {x: []};
              for (let i = 0; i < 7; i++) {
                data.x.push(Math.floor(Math.random() * 100 + 1));
              }
              this.$refs.chartView.drawLine(data)
            }
            this.popupDateVisible = false
          },
    这里用随机数来模拟前两张图的数据变化。

    看看效果:

    完美解决!

    项目地址:https://github.com/JerryYuanJ/a-vue-app-template/tree/master/src/pages/tool/chart

    欢迎star~~~

  • 相关阅读:
    可视化工具搭建SVN服务器
    VS添加lib库以及代码中相对路径的问题
    编程:休息片刻的好处
    我的C++笔记
    【转】缩小mysql数据库的ibdata1文件
    MySQL导库命令
    Java中的serialize接口与transient关键字
    蓝桥杯 算法提高 01背包
    蓝桥杯 算法提高 01背包
    蓝桥杯 算法提高 快乐司机
  • 原文地址:https://www.cnblogs.com/jerryyj/p/9621550.html
Copyright © 2011-2022 走看看