iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 28
0
Modern Web

30天手把手的vue.js教學!系列 第 28

2020it邦鐵人賽-30天手把手的Vue.js教學 Day28 - 關心時事! 做個簡單的COVID-19追蹤app吧!(上)

tags: Vue.js ItIron2020

前言

終於進到最終的三天了,坦白說做為一個教學的系列文,我是很想多示範幾個微型專案做為教學,但我自己在篇幅的分配沒有做得很好,明年參加時我會再特別注意的! 我們將利用剩下的三天打造一個簡單的COVID-19 tracking dashboard。2020對於許多人來說都不是個好年,新冠肺炎打亂了很多計畫,至今半年過去也不見好轉的跡象,了解它的趨勢我想是很重要的一環,那就自己做一個吧!

專案預覽

這個非常簡單的小專案,用我們之前教過的東西就可以打造的小玩意! 做出來的成品會如同以下的demo圖片,會持續追蹤最近一個月內美國境內的確診、康復、使用呼吸器&死亡的人數。你也可以在這個連結玩玩看?

demo

在畫面的部分我用了一些套件讓成品稍微不要這麼單調,其他的部分只要你之前的內容都有聽懂,我想也不是什麼大問題的:D

專案建置

首先一樣請你透過vue-cli打造一個專案,preset我們這次仍選擇default即可

vue create vue create vue-covid19-tracking-demo

安裝完成後,一樣進入專案資料夾,但先不要急著啟動伺服器,我們還有些東西要安裝

cd vue-covid19-tracking-demo

加入vuetify前端框架

接著我們要做一件新的事情~為了讓之後可以專心在邏輯處理上,畫面的部分這次我們要透過vuetify這個CSS框架來做一點協助,就像bootstrap、elementUI或是Bulma等框架一樣,沒什麼特別的! 請你透過以下的指令安裝vuetify框架

vue add vuetify

安裝完成後你應該會順利看到終端機出現新的提示

vue add

我們不太需要額外的設定,這次也選擇Default即可
它會需要一點時間安裝,當結束後請你輸入熟悉的啟動指令

npm run serve

你會發現你在localhost:8080看到的畫面已經不太一樣了
vuetify

透過npm/yarn安裝套件

接下來的流程就簡單多了,請你輸入以下的指令安裝這次我們要使用的套件

npm i chart.js vue-chartjs axios dayjs

如果你不想使用axios,想用之前在天氣app用過的fetch自然也是沒有問題的!

安裝完成後我們先做個簡單的測試,在這個專案中你看到了一些陌生的東西,像是v-app、v-main等,那些都是vuetify中的語意標籤而已~不用太在意! 你目前只要知道所有的城市碼都要包含在v-app內,這樣就可以了!
我們先把不必要的內容刪除,並利用axios看一下是否能正確請求資料。
請你把App.vue檔案修改為以下

<template>
  <v-app>
    <v-main>
      <h1>COVID-19 Tracking Dashboard</h1>
    </v-main>
  </v-app>
</template>

<script>
import axios from 'axios'

export default {
  name: 'App',

  components: {},
  data() {
    return {}
  },
  async created() {
    let { data } = await axios.get(
      'https://api.covidtracking.com/v1/us/daily.json'
    )
    console.log(data)
  },
}
</script>

順利的話你會看到這樣的畫面,記得打開你的devtool~!
vuetify demo3

我們確實取到了一大串的Array of Objects! 隨便點開一個來看吧!

{
    "date": 20201010,
    "states": 56,
    "positive": 7680854,
    "negative": 101450947,
    "pending": 11223,
    "hospitalizedCurrently": 34611,
    "hospitalizedCumulative": 422059,
    "inIcuCurrently": 6681,
    "inIcuCumulative": 21512,
    "onVentilatorCurrently": 1668,
    "onVentilatorCumulative": 2451,
    "recovered": 3062983,
    "dateChecked": "2020-10-10T00:00:00Z",
    "death": 206133,
    "hospitalized": 422059,
    "totalTestResults": 114480836,
    "lastModified": "2020-10-10T00:00:00Z",
    "total": 0,
    "posNeg": 0,
    "deathIncrease": 663,
    "hospitalizedIncrease": 1472,
    "negativeIncrease": 953869,
    "positiveIncrease": 57206,
    "totalTestResultsIncrease": 1133178,
    "hash": "799adb52f30ce10e2966d55b40cfcd345135234d"
}

靈瑯滿目的資料,但我們之後要用到的只有以下幾個

  • date
  • positive
  • hospitalizedCurrently
  • inIcuCurrently
  • onVentilatorCurrently
  • recovered
  • death

最終我們會用這些資料做出六個折線圖表!

快速打造一個簡單的demo圖表!

請你在src/components內新增一個LineChart.vue檔案,並寫入以下的內容

<script>
import { Line } from 'vue-chartjs'

export default {
  extends: Line,
  mounted() {
    const dates = [
      '2020/07/05',
      '2020/07/06',
      '2020/07/07',
      '2020/07/08',
      '2020/07/09',
      '2020/07/10',
    ]
    const totals = [50, 40, 71, 51, 25, 49]

    this.renderChart({
      labels: dates,
      datasets: [
        {
          label: 'demo',
          data: totals,
        },
      ],
    },
    {
      responsive: true,
      maintainAspectRatio: false,
    })
  },
}
</script>

接著再回到App.vue的部分引入該組件,並加在我們標題的下方

<template>
  <v-app>
    <v-main>
      <h1>COVID-19 Tracking Dashboard</h1>
      <LineChart /> //加在這裡
    </v-main>
  </v-app>
</template>

<script>
import axios from 'axios'
import LineChart from './components/LineChart'

export default {
  name: 'App',
  components: {
    LineChart,
  },
  data() {
    return {}
  },
  async created() {
    let { data } = await axios.get(
      'https://api.covidtracking.com/v1/us/daily.json'
    )
    console.log(data)
  },
}
</script>

完成後儲存你的變更,你應該會看到以下的畫面!

vuetify demo3

一點也不好看,不過至少我們成功弄出個圖表了!
在上方的LineChart示範中,有幾個點需要特別注意

  • 我們從vue-chartjs中繼承Line的一些屬性與方法,其中最重要的就是renderChart
  • renderChart接受兩個參數,其中一個是圖表資料,另一個則是options選項
  • 在圖表資料的部分,我們需要兩個陣列(日期&資料)去呈現一個圖表,其中日期dates表示x軸,資料data表示y軸

以上的部分都可以在官方文件中找到,包含你可以傳入的options、複數疊合的圖表等,有興趣的可以查看一下!
現在你知道要利用chart.js做出線圖需要的資料型態,明天開始我們就會加入一些資料傳遞,讓圖表能真正呈現我們透過API取得的資料!

結語

我們今天完成了專案的基本建置,同時介紹了如何利用vue-cli安裝前端框架、以及如何利用chart.js製作最最最基本的圖表,剩下兩天的時間我們會一口氣完成這個簡單的應用程式,希望過程中能讓你有所收穫! 那我們就明天見!

此文章同步發布於個人部落格,有興趣的大大也可以來參觀一下:D


上一篇
2020it邦鐵人賽-30天手把手的Vue.js教學 Day27 - 額外插播: 6個寫vue你應該要知道的Best practices
下一篇
2020it邦鐵人賽-30天手把手的Vue.js教學 Day29 - 關心時事! 做個簡單的COVID-19追蹤app吧!(中)
系列文
30天手把手的vue.js教學!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
xiangtain
iT邦新手 5 級 ‧ 2020-12-22 17:07:36

LineChart.js 檔名寫錯了 應該是.vue

! 感謝提醒,確實是誤植! 已進行修正:D

0
st474ddr
iT邦新手 2 級 ‧ 2021-08-25 11:57:10

您好
小弟想請問目前我嘗試用 axios 去撈資料
可是資料是撈到了,可是卻沒有圖產生
小弟覺得是同步問題
但我已經有做 async await 的處理
另一款 apexChart就不會有這問題@@

以下code (分成兩隻)
// chartTest.vue
template 部分

<line-chart
    v-if="chartData"
    :chartData="chartData"
    :chartOptions="chartOptions"
></line-chart>

script 部分

import lineChart from "../chart/line-chart.vue";
export default {
  components: {
    lineChart,
  }, 
  data: () => ({
    chartData: [],
    chartOptions: {}
  }),
    async created() {
        let api = "../api/test_data.json";
        await this.getChart(api, "chartData1", "chartOptions1");
      },
      methods: {
        async getChart(url, chartData, chartOptions) {
          try {
            let res = await this.$http.get(url);
            this[chartData] = res.data.chartData;
            this[chartOptions] = res.data.chartOptions;
          } catch (err) {
            console.log(err);
          }
        },
      }
 }

//line-chart.vue

import { Line } from "vue-chartjs";

export default {
    extends: Line,
    props: ["chartData", "chartOptions"],
    mounted() {
        this.renderChart(this.chartData, this.chartOptions);
    }
}

這部分可能要看一下完整的程式瑪才有辦法替你debug,因為你的程式瑪我只能看到你call api的過程,渲染的部分我並沒有看到。另外在我看來你的寫法較為特別一些,我自己在寫vue的時候基本上不會特別去操作this,如何顯示API的資料你可以參考下一篇文章。

st474ddr iT邦新手 2 級 ‧ 2021-08-25 13:23:55 檢舉

windate3411 大大您好
感謝回覆
我有補上了完整的 code
我基本上都是照著 vueChartjs 提供的方式撰寫
只是不知道怎麼畫不出來

小弟有個發現
line-chart.vue 總是比 chartTest.vue 先執行
這應該代表DOM先渲染了?
但我created是有下 async / await
應該會等資料拿到才渲染才對吧?

我要留言

立即登入留言