iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
Modern Web

別再說我不會框架,網頁 Vue 起來!系列 第 11

[番外] 來個 Weather App (續)

  • 分享至 

  • twitterImage
  •  

前置作業-HTML & CSS

使用 Google 查 Weather App 會有很多很多的參考,練習不怕沒有畫面,挑一個喜歡的來復刻或是模仿!

畫面的雛形:
demo

改為黃昏時間的查詢 成為追光者

參考 code:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Sunset App</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="./style.css">
  </head>
  <body>
    <section class="search">
      <input type="text">
    </section>
    <section>
      <div class="info-container">
        <div class="info-item">
          <p class="time"> <img src="./img/sea.png" alt="sunset"> 18:30</p>
        </div>
        <div class="info-item">
          <p class="name">Taipei, TW</p>
          <p class="date">2021/09/26</p>
          <p class="des">多雲</p>
        </div>
      </div>
    </section>
  </body>
</html>
* {
  margin: 0;
  padding: 0;
}
img {
  display: inline-block;
}

body {
  font-family: 'Noto Sans', sans-serif;
  font-size: 24px;
  background-image: url(./img/sunset_1127-3503.jpg);
  background-repeat: no-repeat;
  background-size: cover;
  height: 100vh;
  color: #fff;
  padding: 20px;
}

section {
  text-align: center;
}

.search {
  margin-bottom: 40px;
  
}

.search input {
  font-size: 20px;
  border-radius: 10px;
  line-height: 1.5;
  outline: none;
  padding:10px;
}

/* info */
.info-item {
  margin-bottom: 20px;
}

.info-item .time {
  font-size: 60px;
  display: flex;
  justify-content: center;
  align-items: center;
}

Vue 起來

vue-cli 建立專案

$ vue create sunset-app

產生專案架構
new project

將 HTML, CSS 以及圖檔搬進專案中

  • HTML & CSS --> src/App.vue
  • 圖檔 --> src/assets

Vue 實體內容

data

包含 API 的URL, Key, 輸入的城市 以及 回傳的資料

  data () {
    return {
      apiKey: 'xxxxxxx',
      url: 'https://api.openweathermap.org/data/2.5/weather',
      searchCity: '', 
      weather: {} // 存 Response
    }
  }

methods

getWeather 打API

    getWeather (e) {
      if (e.key == "Enter") 
        fetch(`${this.url}?q=${this.searchCity}&units=metric&APPID=${this.apiKey}&lang=zh_tw`)
          .then(res => {
            return res.json();
          }).then(this.setResults);
      }
    },

setResults 存資料

 setResults(data) {
  this.weather = data;
  this.weather.sunset = this.convertTimestampToTime(data.sys.sunset);
 },

convertTimestampToTime 轉換時間

convertTimestampToTime (timestamp) {
  timestamp = timestamp.length == 13 ? timestamp : timestamp*1000;
  let date = new Date(timestamp);
  return `${date.getHours()}:${date.getMinutes()}`;
}

模板綁定資料

搜尋框

<input 
    type="text" 
    v-model="searchCity"
    placeholder="搜尋地區"
    @keypress="getWeather"
>

顯示結果

<div class="info-container" v-if="typeof weather.main != 'undefined'">
    <div class="info-item">
      <p class="time"> <img src="./assets/sea.png" alt="sunset"> {{weather.sunset}}</p>
    </div>
    <div class="info-item" >
      <p class="name">{{weather.name}}, {{weather.sys.country}}</p>
      <p class="des">{{weather.weather[0].description}}</p>
    </div>
</div>

上一篇
[番外] 來個 Weather App (序)
下一篇
[Part 4 ] Vue.js 的精隨-元件 Slots
系列文
別再說我不會框架,網頁 Vue 起來!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言