第12屆鐵人賽Day 15 Vue instance 的 mounted()

昨天在理解Vue的生命週期時提到,Vue在前端處理上有一個透過掛載mounting的hook處理畫面渲染至瀏覽器前的階段。所以我們今天試著在Rails App裡來使用mounted()這個hook實作需求。

本日實作需求:

在做網站的時候通常會需要一些假資料(例如虛擬使用者的nameemailavatar頭像等等),以幫助我們更容易去想像畫面及實際開發功能。 而網路上有一些不錯的第三方API,可以幫助我們創建這些假資料~

我想透過axios從遠端伺服器取得的資料把這個 Face API內的使用者avatar頭像畫面,透過mounted()渲染在前端頁面上! (今天就不掛其他的元件了,把重點focus在理解life cycle hook上)

大概4醬子的感結~~

什麼是axios?

axios是Vue官方推薦的非同步工具,使用getpostpush等Restful(Representational State Transfer: 表現層狀態轉換)規範來取得第三方資料,.then表示取得資料後的處理動作。

常用的方法如下:

axios.request
axios.get
axios.delete
axios.head
axios.post
axios.put
axios.patch

(查資料時發現,另一個前端框架Angular本身有提供了一個簡化的 HTTP 客戶端 API $http,而axios就是之於Vue的類似角色。)

開始進行吧!

Step 0. 使用yarn add安裝並 import axios-on-rails

yarn add axios-on-rails

info Direct dependencies
└─ axios-on-rails@0.0.1
info All dependencies
├─ axios-on-rails@0.0.1
├─ axios@0.17.1
└─ rails-ujs@5.2.4
✨  Done in 5.22s.

Step 1. 在mounted() hook透過axios取得資料

在Vue instance的data選項物件,建立一個subscribers: []的空陣列
透過axios.get取得資料後放入陣列

home.js

import TurbolinksAdapter from 'vue-turbolinks'
import Vue from 'vue/dist/vue.esm'
import Foot from "../components/foot"
import store from './store';
import axios from 'axios-on-rails'


Vue.use(TurbolinksAdapter)


document.addEventListener('turbolinks:load', () => {
  let el = document.querySelector("#content");

  if (el){
    new Vue({
      store,
      el,
      data: {
        day: "第 14 天",
        topic: "Vue instance的 mounting 階段 mounted(): el指定的標籤已經掛載完成",
        audience: "訂閱這個鐵人賽系列文的觀眾:",
        subscribers: []
      },
      mounted() {
        var vm = this
          axios.get('https://tinyfac.es/api/users')
            .then((response) => {
                vm.subscribers = response.data
            })
      },
      components: { Foot }
    })
  }
})

這時console會出現錯誤訊:

Step 2. 解決使用API時,跨網域存取被拒絕問題

在前端開發時使用ajaxaxiosfetch等HTTP Request來存取API資料時有時會遇到CORS(跨來源資源共用,Cross-Origin Resource Sharing)問題,導致無法正常讀取API內容。別擔心!在此使用cors-anywhere就可以順利解決。

程式碼稍加改寫一下:

document.addEventListener('turbolinks:load', () => {
  let el = document.querySelector("#content");
  const cors = 'https://cors-anywhere.herokuapp.com/';
  const url = 'https://tinyfac.es/api/users';

  if (el){
    new Vue({
      store,
      el,
      data: {
        day: "第 14 天",
        topic: "Vue instance的 mounting 階段 mounted(): el指定的標籤已經掛載完成",
        audience: "訂閱這個鐵人賽系列文的觀眾:",
        subscribers: []
      },
      mounted() {
        var vm = this
        // axios.get('https://tinyfac.es/api/users')
        axios.get(`${cors}${url}`)
            .then((response) => {
                vm.subscribers = response.data
            })
      },
      components: { Foot }
    })
  }
})

Step 3. 在Vue instance掛載點中,使用v-foravatar頭像印出來

這個API裡有好大一包json檔,研究資料結構後發現取出imgurl方式是user.avatars[0].url。 所以我們透過v-for,將每位user跑迴圈,並且透過v-bind將資料綁定HTML標籤屬性(不熟的看倌請複習第5天的鐵人賽),img這個標籤裡的src網址與user.avatars[0].url做連動~

<div id="content">
  <div class="main-title">Vue.js x Rails第12屆鐵人賽專案:</div>
  <div class="main-body">本日主題:</div>
  <div class="main-audience"></div>  
  <div class="main-avatar" v-for="user in subscribers">
    <img class="avatar" :src="user.avatars[0].url">
  </div>
  <Foot></Foot>
</div>

備註:avatar的css可以設定為圓形~以符合一般社群網站頭像的顯示風格;)!

  .avatar{
    float: left;
    margin-top: 1em;
    margin-right: 1em;
    position: relative;
    height: 50px;
    width: 50px;

    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
  }

頭像順利印出來啦!

經過半個月與Vue的基礎相處~好像有開始體會到前端框架的有趣之處! 接下來從第16天到第30天,我們要來開發透過資料庫實現功能的Rails網站 feat Vue.js了!

Ref: