最近項目上有這樣一個需求,作統計圖表的展現,可是要在一個頁面實現圖表的切換和按日期條件的查詢。
javascript
相似這樣的。點擊圖標選擇器會彈出一個列表供用戶選擇要看的圖表類型,圖表選定後,點擊右上角的選擇日期會查詢數據刷新當前的圖表。
css
其實,這種需求最簡單的作法,就是將全部的圖表寫在一個界面中。可是每一個圖表的配置項不一樣,圖表一多的話,界面代碼將會很是臃腫且難以維護。因此我沒有使用這種方法。我採起了子路由的方式。vue
首先配置路由:java
{ 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頁面將會只顯示一個選擇器,只有再手動選擇圖表纔會有相應的顯示。
咱們知道,當咱們切換圖表的時候,會調用對應圖表界面的指定方法,這裏的圖表數據展現不會有問題。可是,當咱們選定一張圖表後,想要根據日期來查詢其它數據,可就沒這麼簡單了。你怎麼觸發數據更新呢?git
咱們來看看父路由界面的編碼:github
<!-- @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="width: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="width: 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; width: 100%; line-height: 45px; background: #f5f8fa; border-bottom: 0.03rem solid #eaeaea; font-size: 15px; span { display: inline-block; width: 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 { width: 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 },這裏用隨機數來模擬前兩張圖的數據變化。
看看效果:app
完美解決!dom
項目地址:https://github.com/JerryYuanJ/a-vue-app-template/tree/master/src/pages/tool/chartide
歡迎star~~~
flex